From 522c542a3edaa3a091a1a169ce389e7792ed7d9b Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Tue, 7 Dec 2021 13:09:16 +0530 Subject: [PATCH 01/68] Support for live patching systemVMs and deprecating systemVM.iso. Includes: - fix systemVM template version - Include agent.zip, cloud-scripts.tgz to the commons package - Support for live-patching systemVMs - CPVM, SSVM, Routers - Fix Unit test - Remove systemvm.iso dependency --- .../main/java/com/cloud/event/EventTypes.java | 4 + .../com/cloud/server/ManagementService.java | 2 + .../admin/systemvm/PatchSystemVMCmd.java | 107 +++++++++ .../cloud/agent/api/PatchSystemVmAnswer.java | 44 ++++ .../cloud/agent/api/PatchSystemVmCommand.java | 29 +++ debian/rules | 3 +- engine/schema/pom.xml | 9 +- .../cloud/upgrade/DatabaseUpgradeChecker.java | 9 +- .../upgrade/SystemVmTemplateRegistration.java | 22 +- .../META-INF/db/schema-41600to41610.sql | 3 + engine/schema/templateConfig.sh | 20 +- packaging/centos7/cloud.spec | 7 +- packaging/centos8/cloud.spec | 7 +- packaging/suse15/cloud.spec | 7 +- .../resource/LibvirtComputingResource.java | 10 +- .../LibvirtPatchSystemVmCommandWrapper.java | 132 +++++++++++ .../wrapper/LibvirtStartCommandWrapper.java | 21 ++ .../LibvirtComputingResourceTest.java | 11 +- pom.xml | 1 + .../vm/hypervisor/xenserver/xcpserver/patch | 2 + .../cloud/api/ResponseObjectTypeAdapter.java | 4 + .../cloud/server/ManagementServerImpl.java | 90 +++++++- .../systemd/system/cloud-early-config.service | 7 +- .../etc/systemd/system/cloud-postinit.service | 2 +- .../etc/systemd/system/cloud-preinit.service | 18 ++ .../debian/opt/cloud/bin/setup/bootstrap.sh | 134 +---------- .../debian/opt/cloud/bin/setup/cksnode.sh | 2 +- .../opt/cloud/bin/setup/cloud-early-config | 73 +++--- systemvm/debian/opt/cloud/bin/setup/common.sh | 2 +- .../opt/cloud/bin/setup/consoleproxy.sh | 12 - .../debian/opt/cloud/bin/setup/dhcpsrvr.sh | 16 +- systemvm/debian/opt/cloud/bin/setup/elbvm.sh | 9 - systemvm/debian/opt/cloud/bin/setup/ilbvm.sh | 2 +- systemvm/debian/opt/cloud/bin/setup/init.sh | 217 ++++++++++++++++++ .../debian/opt/cloud/bin/setup/postinit.sh | 16 +- systemvm/debian/opt/cloud/bin/setup/router.sh | 19 -- .../debian/opt/cloud/bin/setup/secstorage.sh | 9 - .../debian/opt/cloud/bin/setup/vpcrouter.sh | 3 +- systemvm/patch-sysvms.sh | 108 +++++++++ systemvm/pom.xml | 6 + tools/appliance/build.sh | 8 +- .../scripts/configure_systemvm_services.sh | 1 + .../appliance/systemvmtemplate/template.json | 4 +- .../java/com/cloud/utils/EncryptionUtil.java | 16 ++ .../java/com/cloud/utils/ssh/SshHelper.java | 42 ++++ 45 files changed, 971 insertions(+), 299 deletions(-) create mode 100644 api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java create mode 100644 core/src/main/java/com/cloud/agent/api/PatchSystemVmAnswer.java create mode 100644 core/src/main/java/com/cloud/agent/api/PatchSystemVmCommand.java create mode 100644 plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java create mode 100644 systemvm/debian/etc/systemd/system/cloud-preinit.service create mode 100644 systemvm/debian/opt/cloud/bin/setup/init.sh create mode 100644 systemvm/patch-sysvms.sh diff --git a/api/src/main/java/com/cloud/event/EventTypes.java b/api/src/main/java/com/cloud/event/EventTypes.java index 84514493e941..470c4de16d00 100644 --- a/api/src/main/java/com/cloud/event/EventTypes.java +++ b/api/src/main/java/com/cloud/event/EventTypes.java @@ -636,6 +636,9 @@ public class EventTypes { // Storage Policies public static final String EVENT_IMPORT_VCENTER_STORAGE_POLICIES = "IMPORT.VCENTER.STORAGE.POLICIES"; + // SystemVM + public static final String EVENT_LIVE_PATCH_SYSTEMVM = "LIVE.PATCH.SYSTEM.VM"; + static { // TODO: need a way to force author adding event types to declare the entity details as well, with out braking @@ -1047,6 +1050,7 @@ public class EventTypes { entityEventDetails.put(EVENT_IMPORT_VCENTER_STORAGE_POLICIES, "StoragePolicies"); entityEventDetails.put(EVENT_IMAGE_STORE_DATA_MIGRATE, ImageStore.class); + entityEventDetails.put(EVENT_LIVE_PATCH_SYSTEMVM, "SystemVMs"); } public static String getEntityForEvent(String eventName) { diff --git a/api/src/main/java/com/cloud/server/ManagementService.java b/api/src/main/java/com/cloud/server/ManagementService.java index a11123139619..27e36ea1fa87 100644 --- a/api/src/main/java/com/cloud/server/ManagementService.java +++ b/api/src/main/java/com/cloud/server/ManagementService.java @@ -39,6 +39,7 @@ import org.apache.cloudstack.api.command.admin.resource.UploadCustomCertificateCmd; import org.apache.cloudstack.api.command.admin.systemvm.DestroySystemVmCmd; import org.apache.cloudstack.api.command.admin.systemvm.ListSystemVMsCmd; +import org.apache.cloudstack.api.command.admin.systemvm.PatchSystemVMCmd; import org.apache.cloudstack.api.command.admin.systemvm.RebootSystemVmCmd; import org.apache.cloudstack.api.command.admin.systemvm.ScaleSystemVMCmd; import org.apache.cloudstack.api.command.admin.systemvm.StopSystemVmCmd; @@ -427,5 +428,6 @@ VirtualMachine upgradeSystemVM(ScaleSystemVMCmd cmd) throws ResourceUnavailableE void cleanupVMReservations(); + Pair patchSystemVM(PatchSystemVMCmd cmd); } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java new file mode 100644 index 000000000000..481e62cffb54 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java @@ -0,0 +1,107 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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.apache.cloudstack.api.command.admin.systemvm; + +import com.cloud.event.EventTypes; +import com.cloud.user.Account; +import com.cloud.utils.Pair; +import com.cloud.vm.VirtualMachine; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.api.response.SystemVmResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.log4j.Logger; + +@APICommand(name = "patchSystemVm", description = "Attempts to live patch systemVMs - CPVM, SSVM, Routers ", + responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, + responseHasSensitiveInfo = false, authorized = { RoleType.Admin }) +public class PatchSystemVMCmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(PatchSystemVMCmd.class.getName()); + private static final String s_name = "patchsystemvmresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = SystemVmResponse.class, + description = "patches systemVM - CPVM/SSVM/Router with the specified ID") + private Long id; + + @Parameter(name = ApiConstants.FORCED, type = CommandType.BOOLEAN, + description = "If true, initiates copy of scripts and restart of the agent if if the template version is the latest." + + "To be used with ID parameter only") + private Boolean force; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + + public Long getId() { + return id; + } + + public boolean isForced() { + return force != null ? force : false; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getEventType() { + return EventTypes.EVENT_LIVE_PATCH_SYSTEMVM; + } + + @Override + public String getEventDescription() { + return String.format("Attempting to live patch System VM with Id: %s ", this._uuidMgr.getUuid(VirtualMachine.class, getId())); + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + Account account = CallContext.current().getCallingAccount(); + if (account != null) { + return account.getId(); + } + + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute() { + Pair patched = _mgr.patchSystemVM(this); + if (patched.first()) { + final SuccessResponse response = new SuccessResponse(getCommandName()); + response.setDisplayText(patched.second()); + setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, patched.second()); + } + } +} diff --git a/core/src/main/java/com/cloud/agent/api/PatchSystemVmAnswer.java b/core/src/main/java/com/cloud/agent/api/PatchSystemVmAnswer.java new file mode 100644 index 000000000000..1065768d6ef2 --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/PatchSystemVmAnswer.java @@ -0,0 +1,44 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.agent.api; + +public class PatchSystemVmAnswer extends Answer { + + String templateVersion; + String scriptsVersion; + + public PatchSystemVmAnswer() { + } + + public PatchSystemVmAnswer(PatchSystemVmCommand cmd, String details, String templateVersion, String scriptsVersion) { + super(cmd, true, details); + this.templateVersion = templateVersion; + this.scriptsVersion = scriptsVersion; + } + + public PatchSystemVmAnswer(PatchSystemVmCommand cmd, String details) { + super(cmd, false, details); + } + + public String getTemplateVersion() { + return this.templateVersion; + } + + public String getScriptsVersion() { + return this.scriptsVersion; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/PatchSystemVmCommand.java b/core/src/main/java/com/cloud/agent/api/PatchSystemVmCommand.java new file mode 100644 index 000000000000..b9ea2d62963b --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/PatchSystemVmCommand.java @@ -0,0 +1,29 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.agent.api; + +public class PatchSystemVmCommand extends GetDomRVersionCmd { + boolean forced; + + public boolean isForced() { + return forced; + } + + public void setForced(boolean forced) { + this.forced = forced; + } +} diff --git a/debian/rules b/debian/rules index ed1559a46dfe..1e7f119f47e9 100755 --- a/debian/rules +++ b/debian/rules @@ -128,7 +128,8 @@ override_dh_auto_install: install -D client/target/utilities/bin/cloud-setup-management $(DESTDIR)/usr/bin/cloudstack-setup-management install -D client/target/utilities/bin/cloud-setup-encryption $(DESTDIR)/usr/bin/cloudstack-setup-encryption install -D client/target/utilities/bin/cloud-sysvmadm $(DESTDIR)/usr/bin/cloudstack-sysvmadm - install -D systemvm/dist/systemvm.iso $(DESTDIR)/usr/share/$(PACKAGE)-common/vms/systemvm.iso + #install -D systemvm/dist/systemvm.iso $(DESTDIR)/usr/share/$(PACKAGE)-common/vms/systemvm.iso + install -D systemvm/dist/* $(DESTDIR)/usr/share/$(PACKAGE)-common/vms/ # We need jasypt for cloud-install-sys-tmplt, so this is a nasty hack to get it into the right place install -D agent/target/dependencies/jasypt-1.9.3.jar $(DESTDIR)/usr/share/$(PACKAGE)-common/lib diff --git a/engine/schema/pom.xml b/engine/schema/pom.xml index edd664eb4c15..adee9110007b 100644 --- a/engine/schema/pom.xml +++ b/engine/schema/pom.xml @@ -73,10 +73,11 @@ - def projectVersion = project.version + def projectVersion = project.properties['project.systemvm.template.version'] + println(projectVersion) String[] versionParts = projectVersion.tokenize('.') - pom.properties['cs.version'] = "4.16" - pom.properties['patch.version'] = "0" + pom.properties['cs.version'] = versionParts[0] + "." + versionParts[1] + pom.properties['patch.version'] = versionParts[2] @@ -146,7 +147,7 @@ bash templateConfig.sh - ${project.version} + ${project.systemvm.template.version} diff --git a/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java b/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java index d2513056216a..1a189c0d2968 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java @@ -369,10 +369,11 @@ public void check() { return; } - SystemVmTemplateRegistration.parseMetadataFile(); - final CloudStackVersion currentVersion = CloudStackVersion.parse(currentVersionValue); - SystemVmTemplateRegistration.CS_MAJOR_VERSION = String.valueOf(currentVersion.getMajorRelease()) + "." + String.valueOf(currentVersion.getMinorRelease()); - SystemVmTemplateRegistration.CS_TINY_VERSION = String.valueOf(currentVersion.getPatchRelease()); + String csVersion = SystemVmTemplateRegistration.parseMetadataFile(); + final CloudStackVersion sysVmVersion = CloudStackVersion.parse(csVersion); + final CloudStackVersion currentVersion = CloudStackVersion.parse(currentVersionValue); + SystemVmTemplateRegistration.CS_MAJOR_VERSION = String.valueOf(sysVmVersion.getMajorRelease()) + "." + String.valueOf(sysVmVersion.getMinorRelease()); + SystemVmTemplateRegistration.CS_TINY_VERSION = String.valueOf(sysVmVersion.getPatchRelease()); s_logger.info("DB version = " + dbVersion + " Code Version = " + currentVersion); diff --git a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java index d788adac8244..4119b11ae508 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java @@ -36,6 +36,7 @@ import com.cloud.upgrade.dao.BasicTemplateDataStoreDaoImpl; import com.cloud.user.Account; import com.cloud.utils.DateUtil; +import com.cloud.utils.EncryptionUtil; import com.cloud.utils.Pair; import com.cloud.utils.UriUtils; import com.cloud.utils.db.GlobalLock; @@ -54,7 +55,6 @@ import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; -import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.ini4j.Ini; @@ -64,7 +64,6 @@ import java.io.File; import java.io.FileReader; import java.io.IOException; -import java.io.InputStream; import java.net.URI; import java.nio.file.Files; import java.nio.file.Path; @@ -351,16 +350,6 @@ public static boolean validateIfSeeded(String url, String path) { } } - private String calculateChecksum(File file) { - try (InputStream is = Files.newInputStream(Paths.get(file.getPath()))) { - return DigestUtils.md5Hex(is); - } catch (IOException e) { - String errMsg = "Failed to calculate template checksum"; - LOGGER.error(errMsg, e); - throw new CloudRuntimeException(errMsg, e); - } - } - public Long getRegisteredTemplateId(Pair hypervisorAndTemplateName) { VMTemplateVO vmTemplate = vmTemplateDao.findLatestTemplateByName(hypervisorAndTemplateName.second()); Long templateId = null; @@ -690,7 +679,7 @@ public void registerTemplate(Pair hypervisorA } } - public static void parseMetadataFile() { + public static String parseMetadataFile() { try { Ini ini = new Ini(); ini.load(new FileReader(METADATA_FILE)); @@ -702,6 +691,8 @@ public static void parseMetadataFile() { NewTemplateChecksum.put(hypervisorType, section.get("checksum")); NewTemplateUrl.put(hypervisorType, section.get("downloadurl")); } + Ini.Section section = ini.get("default"); + return section.get("version"); } catch (Exception e) { String errMsg = String.format("Failed to parse systemVM template metadata file: %s", METADATA_FILE); LOGGER.error(errMsg, e); @@ -735,7 +726,7 @@ private void validateTemplates(Set hypervisorsInUse) } File tempFile = new File(TEMPLATES_PATH + matchedTemplate); - String templateChecksum = calculateChecksum(tempFile); + String templateChecksum = EncryptionUtil.calculateChecksum(tempFile); if (!templateChecksum.equals(NewTemplateChecksum.get(getHypervisorType(hypervisor)))) { LOGGER.error(String.format("Checksum mismatch: %s != %s ", templateChecksum, NewTemplateChecksum.get(getHypervisorType(hypervisor)))); templatesFound = false; @@ -812,9 +803,6 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { private void updateRegisteredTemplateDetails(Long templateId, Map.Entry hypervisorAndTemplateName) { VMTemplateVO templateVO = vmTemplateDao.findById(templateId); templateVO.setTemplateType(Storage.TemplateType.SYSTEM); - if (Hypervisor.HypervisorType.VMware == templateVO.getHypervisorType()) { - templateVO.setDeployAsIs(true); - } boolean updated = vmTemplateDao.update(templateVO.getId(), templateVO); if (!updated) { String errMsg = String.format("updateSystemVmTemplates:Exception while updating template with id %s to be marked as 'system'", templateId); diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41600to41610.sql b/engine/schema/src/main/resources/META-INF/db/schema-41600to41610.sql index bf9cbf861d73..979d87d461e7 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-41600to41610.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-41600to41610.sql @@ -127,3 +127,6 @@ CALL `cloud_usage`.`IDEMPOTENT_ADD_UNIQUE_INDEX`('cloud_usage.usage_volume', 'id -- Add PK to cloud_usage.usage_vpn_user CALL `cloud_usage`.`IDEMPOTENT_ADD_COLUMN`('cloud_usage.usage_vpn_user', 'id', 'BIGINT(20) NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (`id`)'); + +UPDATE `cloud`.`vm_template` set deploy_as_is = 0 where id = 8; + diff --git a/engine/schema/templateConfig.sh b/engine/schema/templateConfig.sh index c3093530e7b2..891c73db1bbf 100644 --- a/engine/schema/templateConfig.sh +++ b/engine/schema/templateConfig.sh @@ -23,8 +23,10 @@ function getTemplateVersion() { subversion1="$(cut -d'.' -f1 <<<"$version")" subversion2="$(cut -d'.' -f2 <<<"$version")" minorversion="$(cut -d'.' -f3 <<<"$version")" + securityversion="$(cut -d'.' -f4 <<<"$version")" export CS_VERSION="${subversion1}"."${subversion2}" export CS_MINOR_VERSION="${minorversion}" + export VERSION="${CS_VERSION}.${CS_MINOR_VERSION}" } function getGenericName() { @@ -52,12 +54,14 @@ function getChecksum() { function createMetadataFile() { local fileData=$(cat $SOURCEFILE) + echo -e "["default"]\nversion = $VERSION.${securityversion}\n" >> $METADATAFILE for i in "${!templates[@]}" do section="$i" hvName=$(getGenericName $i) - templatename="systemvm-${i}-${CS_VERSION}.${CS_MINOR_VERSION}" - checksum=$(getChecksum "$fileData" $hvName) + + templatename="systemvm-${i}-${VERSION}" + checksum=$(getChecksum "$fileData" "$VERSION-$hvName") downloadurl="${templates[$i]}" filename=$(echo ${downloadurl##*'/'}) echo -e "["$section"]\ntemplatename = $templatename\nchecksum = $checksum\ndownloadurl = $downloadurl\nfilename = $filename\n" >> $METADATAFILE @@ -66,12 +70,12 @@ function createMetadataFile() { declare -A templates getTemplateVersion $1 -templates=( ["kvm"]="https://download.cloudstack.org/systemvm/${CS_VERSION}/systemvmtemplate-${CS_VERSION}.${CS_MINOR_VERSION}-kvm.qcow2.bz2" - ["vmware"]="https://download.cloudstack.org/systemvm/${CS_VERSION}/systemvmtemplate-${CS_VERSION}.${CS_MINOR_VERSION}-vmware.ova" - ["xenserver"]="https://download.cloudstack.org/systemvm/$CS_VERSION/systemvmtemplate-$CS_VERSION.$CS_MINOR_VERSION-xen.vhd.bz2" - ["hyperv"]="https://download.cloudstack.org/systemvm/$CS_VERSION/systemvmtemplate-$CS_VERSION.$CS_MINOR_VERSION-hyperv.vhd.zip" - ["lxc"]="https://download.cloudstack.org/systemvm/$CS_VERSION/systemvmtemplate-$CS_VERSION.$CS_MINOR_VERSION-kvm.qcow2.bz2" - ["ovm3"]="https://download.cloudstack.org/systemvm/$CS_VERSION/systemvmtemplate-$CS_VERSION.$CS_MINOR_VERSION-ovm.raw.bz2" ) +templates=( ["kvm"]="https://download.cloudstack.org/systemvm/${CS_VERSION}/systemvmtemplate-$VERSION-kvm.qcow2.bz2" + ["vmware"]="https://download.cloudstack.org/systemvm/${CS_VERSION}/systemvmtemplate-$VERSION-vmware.ova" + ["xenserver"]="https://download.cloudstack.org/systemvm/$CS_VERSION/systemvmtemplate-$VERSION-xen.vhd.bz2" + ["hyperv"]="https://download.cloudstack.org/systemvm/$CS_VERSION/systemvmtemplate-$VERSION-hyperv.vhd.zip" + ["lxc"]="https://download.cloudstack.org/systemvm/$CS_VERSION/systemvmtemplate-$VERSION-kvm.qcow2.bz2" + ["ovm3"]="https://download.cloudstack.org/systemvm/$CS_VERSION/systemvmtemplate-$VERSION-ovm.raw.bz2" ) PARENTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )/dist/systemvm-templates/" diff --git a/packaging/centos7/cloud.spec b/packaging/centos7/cloud.spec index 0e2a5944a0d0..b248cfc3323e 100644 --- a/packaging/centos7/cloud.spec +++ b/packaging/centos7/cloud.spec @@ -231,7 +231,8 @@ mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms mkdir -p ${RPM_BUILD_ROOT}%{python_sitearch}/ mkdir -p ${RPM_BUILD_ROOT}/usr/bin cp -r scripts/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts -install -D systemvm/dist/systemvm.iso ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/systemvm.iso +#install -D systemvm/dist/systemvm.iso ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/systemvm.iso +install -D systemvm/dist/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/ install python/lib/cloud_utils.py ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py cp -r python/lib/cloudutils ${RPM_BUILD_ROOT}%{python_sitearch}/ python3 -m py_compile ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py @@ -600,7 +601,11 @@ pip3 install --upgrade urllib3 %dir %attr(0755,root,root) %{_datadir}/%{name}-common/vms %attr(0755,root,root) %{_datadir}/%{name}-common/scripts %attr(0755,root,root) /usr/bin/cloudstack-sccs +# TODO: Remove systemvm.iso %attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/agent.zip +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/cloud-scripts.tgz +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/patch-sysvms.sh %attr(0644,root,root) %{python_sitearch}/cloud_utils.py %attr(0644,root,root) %{python_sitearch}/__pycache__/* %attr(0644,root,root) %{python_sitearch}/cloudutils/* diff --git a/packaging/centos8/cloud.spec b/packaging/centos8/cloud.spec index 8088ff480c3d..37a374d57e08 100644 --- a/packaging/centos8/cloud.spec +++ b/packaging/centos8/cloud.spec @@ -224,7 +224,8 @@ mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms mkdir -p ${RPM_BUILD_ROOT}%{python_sitearch}/ mkdir -p ${RPM_BUILD_ROOT}/usr/bin cp -r scripts/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts -install -D systemvm/dist/systemvm.iso ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/systemvm.iso +#install -D systemvm/dist/systemvm.iso ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/systemvm.iso +install -D systemvm/dist/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/ install python/lib/cloud_utils.py ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py cp -r python/lib/cloudutils ${RPM_BUILD_ROOT}%{python_sitearch}/ python3 -m py_compile ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py @@ -588,7 +589,11 @@ pip install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz %dir %attr(0755,root,root) %{_datadir}/%{name}-common/vms %attr(0755,root,root) %{_datadir}/%{name}-common/scripts %attr(0755,root,root) /usr/bin/cloudstack-sccs +# TODO: Remove systemvm.iso %attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/agent.zip +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/cloud-scripts.tgz +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/patch-sysvms.sh %attr(0644,root,root) %{python_sitearch}/cloud_utils.py %attr(0644,root,root) %{python_sitearch}/__pycache__/* %attr(0644,root,root) %{python_sitearch}/cloudutils/* diff --git a/packaging/suse15/cloud.spec b/packaging/suse15/cloud.spec index 7e5c38fb9748..23bce9fc92e1 100644 --- a/packaging/suse15/cloud.spec +++ b/packaging/suse15/cloud.spec @@ -226,7 +226,8 @@ mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms mkdir -p ${RPM_BUILD_ROOT}%{python_sitearch}/ mkdir -p ${RPM_BUILD_ROOT}/usr/bin cp -r scripts/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts -install -D systemvm/dist/systemvm.iso ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/systemvm.iso +#install -D systemvm/dist/systemvm.iso ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/systemvm.iso +install -D systemvm/dist/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/ install python/lib/cloud_utils.py ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py cp -r python/lib/cloudutils ${RPM_BUILD_ROOT}%{python_sitearch}/ python3 -m py_compile ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py @@ -582,7 +583,11 @@ pip install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz %dir %attr(0755,root,root) %{_datadir}/%{name}-common/vms %attr(0755,root,root) %{_datadir}/%{name}-common/scripts %attr(0755,root,root) /usr/bin/cloudstack-sccs +# TODO: Remove systemvm.iso %attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/agent.zip +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/cloud-scripts.tgz +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/patch-sysvms.sh %attr(0644,root,root) %{python_sitearch}/cloud_utils.py %attr(0644,root,root) %{python_sitearch}/__pycache__/* %attr(0644,root,root) %{python_sitearch}/cloudutils/* diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index f1c0ce8153c9..a3257f9967bd 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -279,6 +279,10 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv private static final String AARCH64 = "aarch64"; public static final String RESIZE_NOTIFY_ONLY = "NOTIFYONLY"; + public static final String BASEPATH = "/usr/share/cloudstack-common/vms/"; + + public static String[] srcFiles = new String[] { "agent.zip", "cloud-scripts.tgz" }; + public static String[] newSrcFiles = new String[] { "agent.zip", "cloud-scripts.tgz", "patch-sysvms.sh" }; private String _modifyVlanPath; private String _versionstringpath; @@ -402,7 +406,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv s_powerStatesTable.put(DomainState.VIR_DOMAIN_SHUTDOWN, PowerState.PowerOff); } - private VirtualRoutingResource _virtRouterResource; + public VirtualRoutingResource _virtRouterResource; private String _pingTestPath; @@ -462,7 +466,7 @@ public ExecutionResult createFileInVR(final String routerIp, final String path, try { SshHelper.scpTo(routerIp, 3922, "root", permKey, null, path, content.getBytes(), filename, null); } catch (final Exception e) { - s_logger.warn("Fail to create file " + path + filename + " in VR " + routerIp, e); + s_logger.warn("Failed to create file " + path + filename + " in VR " + routerIp, e); details = e.getMessage(); success = false; } @@ -2905,7 +2909,7 @@ public int compare(final DiskTO arg0, final DiskTO arg1) { if (vmSpec.getType() != VirtualMachine.Type.User) { if (_sysvmISOPath != null) { final DiskDef iso = new DiskDef(); - iso.defISODisk(_sysvmISOPath); + // iso.defISODisk(_sysvmISOPath); if (_guestCpuArch != null && _guestCpuArch.equals("aarch64")) { iso.setBusType(DiskDef.DiskBus.SCSI); } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java new file mode 100644 index 000000000000..392ccb6e6584 --- /dev/null +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java @@ -0,0 +1,132 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.hypervisor.kvm.resource.wrapper; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.PatchSystemVmAnswer; +import com.cloud.agent.api.PatchSystemVmCommand; +import com.cloud.agent.api.routing.NetworkElementCommand; +import com.cloud.agent.resource.virtualnetwork.VRScripts; +import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource; +import com.cloud.resource.CommandWrapper; +import com.cloud.resource.ResourceWrapper; +import com.cloud.utils.EncryptionUtil; +import com.cloud.utils.ExecutionResult; +import com.cloud.utils.Pair; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; +import com.cloud.utils.ssh.SshHelper; +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Logger; + +import java.io.File; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +@ResourceWrapper(handles = PatchSystemVmCommand.class) +public class LibvirtPatchSystemVmCommandWrapper extends CommandWrapper { + private static final Logger s_logger = Logger.getLogger(LibvirtPatchSystemVmCommandWrapper.class); + private static int sshPort = Integer.parseInt(LibvirtComputingResource.DEFAULTDOMRSSHPORT); + private static File pemFile = new File(LibvirtComputingResource.SSHPRVKEYPATH); + + @Override + public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverResource) { + final String controlIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); + final String sysVMName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + ExecutionResult result; + try { + result = getSystemVmVersionAndChecksum(serverResource, controlIp); + scpPatchFiles(controlIp); + } catch (CloudRuntimeException e) { + return new PatchSystemVmAnswer(cmd, e.getMessage()); + } + + final String[] lines = result.getDetails().split("&"); + // TODO: do we fail, or patch anyway?? + if (lines.length != 2) { + return new PatchSystemVmAnswer(cmd, result.getDetails()); + } + + String scriptChecksum = lines[1].trim(); + String checksum = calculateCurrentChecksum(sysVMName).trim(); + + if (!StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum)) { + if (!cmd.isForced()) { + String msg = String.format("No change in the scripts checksum, not patching systemVM %s", sysVMName); + s_logger.info(msg); + return new PatchSystemVmAnswer(cmd, msg, lines[0], lines[1]); + } + } + + Pair patchResult = null; + try { + patchResult = SshHelper.sshExecute(controlIp, sshPort, "root", + pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 60000); + } catch (Exception e) { + return new PatchSystemVmAnswer(cmd, e.getMessage()); + } + + if (patchResult.first()) { + return new PatchSystemVmAnswer(cmd, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], lines[1]); + } + return new PatchSystemVmAnswer(cmd, patchResult.second()); + } + + private String calculateCurrentChecksum(String name) { + String cloudScriptsPath = Script.findScript("", "vms/cloud-scripts.tgz"); + if (cloudScriptsPath == null) { + throw new CloudRuntimeException(String.format("Unable to find cloudScripts path, cannot update SystemVM %s", name)); + } + String md5sum = EncryptionUtil.calculateChecksum(new File(cloudScriptsPath)); + return md5sum; + } + + private ExecutionResult getSystemVmVersionAndChecksum(LibvirtComputingResource serverResource, String controlIp) { + ExecutionResult result; + try { + result = serverResource.executeInVR(controlIp, VRScripts.VERSION, null); + if (!result.isSuccess()) { + String errMsg = String.format("GetSystemVMVersionCmd on %s failed, message %s", controlIp, result.getDetails()); + s_logger.error(errMsg); + throw new CloudRuntimeException(errMsg); + } + } catch (final Exception e) { + final String msg = "GetSystemVMVersionCmd failed due to " + e; + s_logger.error(msg, e); + throw new CloudRuntimeException(msg, e); + } + return result; + } + + private void scpPatchFiles(String controlIp) { + try { + List srcFiles = Arrays.asList(LibvirtComputingResource.newSrcFiles); + srcFiles = srcFiles.stream() + .map(file -> LibvirtComputingResource.BASEPATH + file) // Using Lambda notation to update the entries + .collect(Collectors.toList()); + String[] newSrcFiles = srcFiles.toArray(new String[0]); + SshHelper.scpTo(controlIp, sshPort, "root", pemFile, null, + "/home/cloud/", newSrcFiles, "0755"); + } catch (Exception e) { + String errMsg = "Failed to scp files to system VM"; + s_logger.error(errMsg, e); + throw new CloudRuntimeException(errMsg, e); + } + } +} + diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java index f151255d5cdc..b95c163e7081 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java @@ -19,8 +19,13 @@ package com.cloud.hypervisor.kvm.resource.wrapper; +import java.io.File; import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import com.cloud.utils.ssh.SshHelper; import org.apache.log4j.Logger; import org.libvirt.Connect; import org.libvirt.DomainInfo.DomainState; @@ -115,6 +120,22 @@ public Answer execute(final StartCommand command, final LibvirtComputingResource break; } } + + try { + List srcFiles = Arrays.asList(LibvirtComputingResource.srcFiles); + srcFiles = srcFiles.stream() + .map(file -> LibvirtComputingResource.BASEPATH + file) + .collect(Collectors.toList()); + File pemFile = new File(LibvirtComputingResource.SSHPRVKEYPATH); + SshHelper.scpTo(controlIp, 3922, "root", pemFile, null, + "/home/cloud/", srcFiles.toArray(new String[0]), "0755"); + // TODO: May want to remove this when cert patching logic is moved + Thread.sleep(10000); + } catch (Exception e) { + String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; + s_logger.error(errMsg, e); + return new StartAnswer(command, String.format("%s due to: %s", errMsg, e.getMessage())); + } } } diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java index 1f6545881795..f13ac238cfea 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java @@ -54,6 +54,7 @@ import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; +import com.cloud.utils.ssh.SshHelper; import org.apache.cloudstack.storage.command.AttachAnswer; import org.apache.cloudstack.storage.command.AttachCommand; import org.apache.cloudstack.utils.linux.CPUStat; @@ -210,7 +211,7 @@ import org.libvirt.VcpuInfo; @RunWith(PowerMockRunner.class) -@PrepareForTest(value = {MemStat.class}) +@PrepareForTest(value = {MemStat.class, SshHelper.class}) @PowerMockIgnore({"javax.xml.*", "org.w3c.dom.*", "org.apache.xerces.*"}) public class LibvirtComputingResourceTest { @@ -5278,7 +5279,9 @@ public void testStartCommandUriException() { } @Test - public void testStartCommand() { + public void testStartCommand() throws Exception { + PowerMockito.mockStatic(SshHelper.class); + PowerMockito.doNothing().when(SshHelper.class, "scpTo", Mockito.anyString(), Mockito.anyInt(), Mockito.anyString(), Mockito.any(File.class), nullable(String.class), Mockito.anyString(), Mockito.any(String[].class), Mockito.anyString()); final VirtualMachineTO vmSpec = Mockito.mock(VirtualMachineTO.class); final com.cloud.host.Host host = Mockito.mock(com.cloud.host.Host.class); final boolean executeInSequence = false; @@ -5352,7 +5355,9 @@ public void testStartCommand() { } @Test - public void testStartCommandIsolationEc2() { + public void testStartCommandIsolationEc2() throws Exception { + PowerMockito.mockStatic(SshHelper.class); + PowerMockito.doNothing().when(SshHelper.class, "scpTo", Mockito.anyString(), Mockito.anyInt(), Mockito.anyString(), Mockito.any(File.class), nullable(String.class), Mockito.anyString(), Mockito.any(String[].class), Mockito.anyString()); final VirtualMachineTO vmSpec = Mockito.mock(VirtualMachineTO.class); final com.cloud.host.Host host = Mockito.mock(com.cloud.host.Host.class); final boolean executeInSequence = false; diff --git a/pom.xml b/pom.xml index cfea12556552..718430eb867e 100644 --- a/pom.xml +++ b/pom.xml @@ -49,6 +49,7 @@ UTF-8 UTF-8 + 4.16.0.0 11 diff --git a/scripts/vm/hypervisor/xenserver/xcpserver/patch b/scripts/vm/hypervisor/xenserver/xcpserver/patch index 862aa2e9c110..32c7c46728d8 100644 --- a/scripts/vm/hypervisor/xenserver/xcpserver/patch +++ b/scripts/vm/hypervisor/xenserver/xcpserver/patch @@ -32,6 +32,8 @@ vmops=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +agent.zip=../../../../../vms,0644,/opt/xensource/packages/iso +cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/iso id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin setupxenserver.sh=..,0755,/opt/cloud/bin diff --git a/server/src/main/java/com/cloud/api/ResponseObjectTypeAdapter.java b/server/src/main/java/com/cloud/api/ResponseObjectTypeAdapter.java index 44baedc933b1..f6f777efe3f9 100644 --- a/server/src/main/java/com/cloud/api/ResponseObjectTypeAdapter.java +++ b/server/src/main/java/com/cloud/api/ResponseObjectTypeAdapter.java @@ -22,6 +22,7 @@ import org.apache.cloudstack.api.ResponseObject; import org.apache.cloudstack.api.response.ExceptionResponse; import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import com.google.gson.JsonElement; @@ -38,6 +39,9 @@ public JsonElement serialize(ResponseObject responseObj, Type typeOfResponseObj, if (responseObj instanceof SuccessResponse) { obj.addProperty("success", ((SuccessResponse)responseObj).getSuccess()); + if (!StringUtils.isEmpty(((SuccessResponse) responseObj).getDisplayText())) { + obj.addProperty("details", ((SuccessResponse)responseObj).getDisplayText()); + } return obj; } else if (responseObj instanceof ExceptionResponse) { obj.addProperty("errorcode", ((ExceptionResponse)responseObj).getErrorCode()); diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index cc53eed7d644..2a0734d7ec3a 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -44,8 +44,15 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.agent.api.PatchSystemVmAnswer; +import com.cloud.agent.api.PatchSystemVmCommand; +import com.cloud.agent.api.routing.NetworkElementCommand; import com.cloud.dc.DomainVlanMapVO; import com.cloud.dc.dao.DomainVlanMapDao; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.network.Networks; +import com.cloud.vm.NicVO; +import com.cloud.vm.dao.NicDao; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.affinity.AffinityGroupProcessor; import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; @@ -225,6 +232,7 @@ import org.apache.cloudstack.api.command.admin.systemvm.DestroySystemVmCmd; import org.apache.cloudstack.api.command.admin.systemvm.ListSystemVMsCmd; import org.apache.cloudstack.api.command.admin.systemvm.MigrateSystemVMCmd; +import org.apache.cloudstack.api.command.admin.systemvm.PatchSystemVMCmd; import org.apache.cloudstack.api.command.admin.systemvm.RebootSystemVmCmd; import org.apache.cloudstack.api.command.admin.systemvm.ScaleSystemVMCmd; import org.apache.cloudstack.api.command.admin.systemvm.StartSystemVMCmd; @@ -763,6 +771,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe static final ConfigKey sshKeyLength = new ConfigKey("Advanced", Integer.class, "ssh.key.length", "2048", "Specifies custom SSH key length (bit)", true, ConfigKey.Scope.Global); static final ConfigKey humanReadableSizes = new ConfigKey("Advanced", Boolean.class, "display.human.readable.sizes", "true", "Enables outputting human readable byte sizes to logs and usage records.", false, ConfigKey.Scope.Global); public static final ConfigKey customCsIdentifier = new ConfigKey("Advanced", String.class, "custom.cs.identifier", UUID.randomUUID().toString().split("-")[0].substring(4), "Custom identifier for the cloudstack installation", true, ConfigKey.Scope.Global); + private static final VirtualMachine.Type []systemVmTypes = { VirtualMachine.Type.SecondaryStorageVm, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.DomainRouter }; @Inject public AccountManager _accountMgr; @@ -825,7 +834,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe @Inject private StoragePoolJoinDao _poolJoinDao; @Inject - private NetworkDao _networkDao; + private NetworkDao networkDao; @Inject private StorageManager _storageMgr; @Inject @@ -898,6 +907,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe private AnnotationDao annotationDao; @Inject private DomainVlanMapDao _domainVlanMapDao; + @Inject + private NicDao nicDao; private LockControllerListener _lockControllerListener; private final ScheduledExecutorService _eventExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("EventChecker")); @@ -2172,9 +2183,9 @@ public Pair, Integer> searchForIPAddresses(final ListP if (ip == null) { throw new InvalidParameterValueException("Please specify a valid ipaddress id"); } - network = _networkDao.findById(ip.getSourceNetworkId()); + network = networkDao.findById(ip.getSourceNetworkId()); } else { - network = _networkDao.findById(networkId); + network = networkDao.findById(networkId); } if (network == null || network.getGuestType() != Network.GuestType.Shared) { throw new InvalidParameterValueException("Please specify a valid network id"); @@ -2236,7 +2247,7 @@ public Pair, Integer> searchForIPAddresses(final ListP } if (associatedNetworkId != null) { - _accountMgr.checkAccess(caller, null, false, _networkDao.findById(associatedNetworkId)); + _accountMgr.checkAccess(caller, null, false, networkDao.findById(associatedNetworkId)); sc.setParameters("associatedNetworkIdEq", associatedNetworkId); } if (vpcId != null) { @@ -2252,7 +2263,7 @@ public Pair, Integer> searchForIPAddresses(final ListP Long zoneId = zone; Account owner = _accountMgr.finalizeOwner(CallContext.current().getCallingAccount(), cmd.getAccountName(), cmd.getDomainId(), cmd.getProjectId()); if (associatedNetworkId != null) { - NetworkVO guestNetwork = _networkDao.findById(associatedNetworkId); + NetworkVO guestNetwork = networkDao.findById(associatedNetworkId); if (zoneId == null) { zoneId = guestNetwork.getDataCenterId(); } else if (zoneId != guestNetwork.getDataCenterId()) { @@ -3527,6 +3538,7 @@ public List> getCommands() { cmdList.add(UploadResourceIconCmd.class); cmdList.add(DeleteResourceIconCmd.class); cmdList.add(ListResourceIconCmd.class); + cmdList.add(PatchSystemVMCmd.class); // Out-of-band management APIs for admins cmdList.add(EnableOutOfBandManagementForHostCmd.class); @@ -3932,7 +3944,7 @@ public Map listCapabilities(final ListCapabilitiesCmd cmd) { boolean elasticLoadBalancerEnabled = false; boolean KVMSnapshotEnabled = false; String supportELB = "false"; - final List networks = _networkDao.listSecurityGroupEnabledNetworks(); + final List networks = networkDao.listSecurityGroupEnabledNetworks(); if (networks != null && !networks.isEmpty()) { securityGroupsEnabled = true; final String elbEnabled = _configDao.getValue(Config.ElasticLoadBalancerEnabled.key()); @@ -4633,6 +4645,72 @@ public void cleanupVMReservations() { _dpMgr.cleanupVMReservations(); } + @Override + public Pair patchSystemVM(PatchSystemVMCmd cmd) { + Long systemVmId = cmd.getId(); + boolean forced = cmd.isForced(); + + if (systemVmId == null) { + throw new InvalidParameterValueException("Please provide a valid ID of a system VM to be patched"); + } + + final VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(systemVmId, systemVmTypes); + if (systemVm == null) { + throw new InvalidParameterValueException("Unable to find SystemVm with id " + systemVmId); + } + + return updateSystemVM(systemVm, forced); + } + + + private String getControlIp(final long systemVmId) { + String controlIpAddress = null; + final List nics = nicDao.listByVmId(systemVmId); + for (final NicVO n : nics) { + final NetworkVO nc = networkDao.findById(n.getNetworkId()); + if (nc != null && nc.getTrafficType() == Networks.TrafficType.Control) { + controlIpAddress = n.getIPv4Address(); + // router will have only one control IP + break; + } + } + + if (controlIpAddress == null) { + s_logger.warn("Unable to find systemVm's control ip in its attached NICs!. systemVmId: " + systemVmId); + VMInstanceVO systemVM = _vmInstanceDao.findById(systemVmId); + return systemVM.getPrivateIpAddress(); + } + + return controlIpAddress; + } + + private Pair updateSystemVM(VMInstanceVO systemVM, boolean forced) { + return patchSystemVm(systemVM, forced); + } + + private Pair patchSystemVm(VMInstanceVO systemVM, boolean forced) { + PatchSystemVmAnswer answer = new PatchSystemVmAnswer(); + final PatchSystemVmCommand command = new PatchSystemVmCommand(); + command.setAccessDetail(NetworkElementCommand.ROUTER_IP, getControlIp(systemVM.getId())); + command.setAccessDetail(NetworkElementCommand.ROUTER_NAME, systemVM.getInstanceName()); + command.setForced(forced); + try { + answer = (PatchSystemVmAnswer) _agentMgr.send(systemVM.getHostId(), command); + if (!answer.getResult()) { + String errMsg = String.format("Failed to patch systemVM %s due to %s", systemVM.getInstanceName(), answer.getDetails()); + s_logger.error(errMsg); + return new Pair<>(false, errMsg); + } + + } catch (AgentUnavailableException | OperationTimedoutException e) { + String errMsg = "SystemVM live patch failed"; + s_logger.error(errMsg, e); + return new Pair<>(false, String.format("%s due to: %s", errMsg, e.getMessage())); + } + s_logger.info(String.format("Successfully patch system VM %s", systemVM.getInstanceName())); + return new Pair<>(true, answer.getDetails()); + } + public List getStoragePoolAllocators() { return _storagePoolAllocators; } diff --git a/systemvm/debian/etc/systemd/system/cloud-early-config.service b/systemvm/debian/etc/systemd/system/cloud-early-config.service index 2af52767cc39..cfaf5e7cd44a 100644 --- a/systemvm/debian/etc/systemd/system/cloud-early-config.service +++ b/systemvm/debian/etc/systemd/system/cloud-early-config.service @@ -2,11 +2,8 @@ Description=CloudStack post-boot patching service using cmdline DefaultDependencies=no -Before=network-pre.target -Wants=network-pre.target - -Requires=local-fs.target -After=local-fs.target +Requires=local-fs.target cloud-preinit.service +After=local-fs.target cloud-preinit.service [Install] WantedBy=multi-user.target diff --git a/systemvm/debian/etc/systemd/system/cloud-postinit.service b/systemvm/debian/etc/systemd/system/cloud-postinit.service index cb20aaf7c060..f5b23e230877 100644 --- a/systemvm/debian/etc/systemd/system/cloud-postinit.service +++ b/systemvm/debian/etc/systemd/system/cloud-postinit.service @@ -1,7 +1,7 @@ [Unit] Description=CloudStack post-patching init script After=cloud-early-config.service network.target local-fs.target -Before=ssh.service +#Before=ssh.service [Install] WantedBy=multi-user.target diff --git a/systemvm/debian/etc/systemd/system/cloud-preinit.service b/systemvm/debian/etc/systemd/system/cloud-preinit.service new file mode 100644 index 000000000000..373cd9ed66fa --- /dev/null +++ b/systemvm/debian/etc/systemd/system/cloud-preinit.service @@ -0,0 +1,18 @@ +[Unit] +Description=CloudStack service to initialize interfaces +DefaultDependencies=no + +Before=network-pre.target +Wants=network-pre.target + +Requires=local-fs.target +After=local-fs.target + +[Install] +WantedBy=multi-user.target + +[Service] +Type=oneshot +ExecStart=/opt/cloud/bin/setup/init.sh +RemainAfterExit=true +TimeoutStartSec=5min diff --git a/systemvm/debian/opt/cloud/bin/setup/bootstrap.sh b/systemvm/debian/opt/cloud/bin/setup/bootstrap.sh index 2335d649a950..3f64be778232 100755 --- a/systemvm/debian/opt/cloud/bin/setup/bootstrap.sh +++ b/systemvm/debian/opt/cloud/bin/setup/bootstrap.sh @@ -15,7 +15,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. - +set -x PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" CMDLINE=/var/cache/cloud/cmdline @@ -29,124 +29,6 @@ log_it() { log_action_msg "$@" } -hypervisor() { - if [ -d /proc/xen ]; then - mount -t xenfs none /proc/xen - $(dmesg | grep -q "Xen HVM") - if [ $? -eq 0 ]; then # 1=PV,0=HVM - echo "xen-hvm" && return 0 - else - echo "xen-pv" && return 0 - fi - fi - - [ -x /usr/sbin/virt-what ] && local facts=( $(virt-what) ) - if [ "$facts" != "" ]; then - # Xen HVM is recognized as Hyperv when Viridian extensions are enabled - if [ "${facts[-1]}" == "xen-domU" ] && [ "${facts[0]}" == "hyperv" ]; then - echo "xen-hvm" && return 0 - else - echo ${facts[-1]} && return 0 - fi - fi - - grep -q QEMU /proc/cpuinfo && echo "kvm" && return 0 - grep -q QEMU /var/log/messages && echo "kvm" && return 0 - - vmware-checkvm &> /dev/null && echo "vmware" && return 0 - - echo "unknown" && return 1 -} - -config_guest() { - [ ! -d /proc/xen ] && sed -i 's/^vc/#vc/' /etc/inittab && telinit q - [ -d /proc/xen ] && sed -i 's/^#vc/vc/' /etc/inittab && telinit q - - systemctl daemon-reload - - case $HYPERVISOR in - xen-pv|xen-domU) - systemctl stop ntpd - systemctl disable ntpd - systemctl enable xe-daemon - systemctl start xe-daemon - - cat /proc/cmdline > $CMDLINE - sed -i "s/%/ /g" $CMDLINE - ;; - xen-hvm) - systemctl stop ntpd - systemctl disable ntpd - systemctl enable xe-daemon - systemctl start xe-daemon - - if [ ! -f /usr/bin/xenstore-read ]; then - log_it "ERROR: xentools not installed, cannot found xenstore-read" && exit 5 - fi - /usr/bin/xenstore-read vm-data/cloudstack/init > $CMDLINE - sed -i "s/%/ /g" $CMDLINE - ;; - kvm) - # Configure kvm hotplug support - if grep -E 'CONFIG_HOTPLUG_PCI=y|CONFIG_HOTPLUG_PCI_ACPI=y' /boot/config-`uname -r`; then - log_it "acpiphp and pci_hotplug module already compiled in" - else - modprobe acpiphp 2> /dev/null && log_it "acpiphp module loaded" || true - modprobe pci_hotplug 2> /dev/null && log_it "pci_hotplug module loaded" || true - fi - - sed -i -e "/^s0:2345:respawn.*/d" /etc/inittab - sed -i -e "/6:23:respawn/a\s0:2345:respawn:/sbin/getty -L 115200 ttyS0 vt102" /etc/inittab - systemctl enable qemu-guest-agent - systemctl start qemu-guest-agent - - # Wait for $CMDLINE file to be written by the qemu-guest-agent - for i in {1..60}; do - if [ -s $CMDLINE ]; then - log_it "Received a new non-empty cmdline file from qemu-guest-agent" - # Remove old configuration files in /etc/cloudstack if VR is booted from cloudstack - rm -rf /etc/cloudstack/*.json - log_it "Booting from cloudstack, remove old configuration files in /etc/cloudstack/" - break - fi - sleep 1 - done - if [ ! -s $CMDLINE ]; then - log_it "Failed to receive the cmdline file via the qemu-guest-agent" - fi - ;; - vmware) - # system time sync'd with host via vmware tools - systemctl stop ntpd - systemctl disable ntpd - systemctl enable open-vm-tools - systemctl start open-vm-tools - - vmtoolsd --cmd 'machine.id.get' > $CMDLINE - ;; - virtualpc|hyperv) - # Hyper-V is recognized as virtualpc hypervisor type. Boot args are passed using KVP Daemon - systemctl enable hyperv-daemons.hv-fcopy-daemon.service hyperv-daemons.hv-kvp-daemon.service hyperv-daemons.hv-vss-daemon.service - systemctl start hyperv-daemons.hv-fcopy-daemon.service hyperv-daemons.hv-kvp-daemon.service hyperv-daemons.hv-vss-daemon.service - sleep 5 - cp -f /var/opt/hyperv/.kvp_pool_0 $CMDLINE - cat /dev/null > /var/opt/hyperv/.kvp_pool_0 - ;; - virtualbox) - # Virtualbox is used to test the virtual router - # get the commandline from a dmistring (yes, hacky!) - dmidecode | grep cmdline | sed 's/^.*cmdline://' > $CMDLINE - RV=$? - if [ $RV -ne 0 ] ; then - log_it "Failed to get cmdline from a virtualbox dmi property" - fi - ;; - esac - - # Find and export guest type - export TYPE=$(grep -Po 'type=\K[a-zA-Z]*' $CMDLINE) -} - patch_systemvm() { local patchfile=$1 local backupfolder="/tmp/.conf.backup" @@ -158,6 +40,8 @@ patch_systemvm() { fi rm /usr/local/cloud/systemvm -rf mkdir -p /usr/local/cloud/systemvm + ls -lrt $patchfile + echo "All" | unzip $patchfile -d /usr/local/cloud/systemvm >$logfile 2>&1 find /usr/local/cloud/systemvm/ -name \*.sh | xargs chmod 555 if [ -f $backupfolder/cloud.jks ]; then @@ -171,7 +55,7 @@ patch_systemvm() { } patch() { - local PATCH_MOUNT=/media/cdrom + local PATCH_MOUNT=/home/cloud local logfile="/var/log/patchsystemvm.log" if [ "$TYPE" == "consoleproxy" ] || [ "$TYPE" == "secstorage" ] && [ -f ${PATCH_MOUNT}/agent.zip ] && [ -f /var/cache/cloud/patch.required ] @@ -188,11 +72,7 @@ patch() { rm -f /var/cache/cloud/patch.required chmod -x /etc/systemd/system/cloud*.service systemctl daemon-reload - umount $PATCH_MOUNT || true - if [ -f /mnt/cmdline ]; then - cat /mnt/cmdline > $CMDLINE - fi return 0 } @@ -212,11 +92,7 @@ config_sysctl() { bootstrap() { log_it "Bootstrapping systemvm appliance" - export HYPERVISOR=$(hypervisor) - [ $? -ne 0 ] && log_it "Failed to detect hypervisor type, bailing out" && exit 10 - log_it "Starting guest services for $HYPERVISOR" - - config_guest + export TYPE=$(grep -Po 'type=\K[a-zA-Z]*' $CMDLINE) patch config_sysctl diff --git a/systemvm/debian/opt/cloud/bin/setup/cksnode.sh b/systemvm/debian/opt/cloud/bin/setup/cksnode.sh index a864d188d009..612fdd477e8f 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cksnode.sh +++ b/systemvm/debian/opt/cloud/bin/setup/cksnode.sh @@ -39,7 +39,7 @@ setup_k8s_node() { log_it "Swap disabled" log_it "Setting up interfaces" - setup_common eth0 +# setup_common eth0 setup_system_rfc1918_internal log_it "Setting up entry in hosts" diff --git a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config index d0ebd0b68146..9695b18307bb 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config +++ b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config @@ -15,7 +15,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. - +set -x PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" # Clear boot up flag, it would be created by rc.local after boot up done @@ -32,53 +32,61 @@ log_it() { } patch() { - local PATCH_MOUNT=/media/cdrom + local PATCH_MOUNT=/home/cloud local patchfile=$PATCH_MOUNT/cloud-scripts.tgz local privkey=$PATCH_MOUNT/authorized_keys local md5file=/var/cache/cloud/cloud-scripts-signature local cdrom_dev= mkdir -p $PATCH_MOUNT - if [ -e /dev/xvdd ]; then - cdrom_dev=/dev/xvdd - elif [ -e /dev/cdrom ]; then - cdrom_dev=/dev/cdrom - elif [ -e /dev/cdrom1 ]; then - cdrom_dev=/dev/cdrom1 - elif [ -e /dev/cdrom2 ]; then - cdrom_dev=/dev/cdrom2 - elif [ -e /dev/cdrom3 ]; then - cdrom_dev=/dev/cdrom3 - fi - if [ -f /var/cache/cloud/authorized_keys ]; then privkey=/var/cache/cloud/authorized_keys fi - if [ -n "$cdrom_dev" ]; then - mount -o ro $cdrom_dev $PATCH_MOUNT - local oldmd5= - [ -f ${md5file} ] && oldmd5=$(cat ${md5file}) - local newmd5= - [ -f ${patchfile} ] && newmd5=$(md5sum ${patchfile} | awk '{print $1}') - log_it "Scripts checksum detected: oldmd5=$oldmd5 newmd5=$newmd5" - if [ "$oldmd5" != "$newmd5" ] && [ -f ${patchfile} ] && [ "$newmd5" != "" ] - then - tar xzf $patchfile -C / - echo ${newmd5} > ${md5file} - log_it "Patched scripts using $patchfile" - touch /var/cache/cloud/patch.required + retry=60 + local patched=false + while [ $retry -gt 0 ] + do + if [ -f $patchfile ]; then + local oldmd5= + [ -f ${md5file} ] && oldmd5=$(cat ${md5file}) + local newmd5= + [ -f ${patchfile} ] && newmd5=$(md5sum ${patchfile} | awk '{print $1}') + log_it "Scripts checksum detected: oldmd5=$oldmd5 newmd5=$newmd5" + log_it ls -lrt $PATCH_MOUNT + if [ "$oldmd5" != "$newmd5" ] && [ -f ${patchfile} ] && [ "$newmd5" != "" ] + then + tar xzf $patchfile -C / + ls -lrt /opt/cloud/bin/keystore* + echo ${newmd5} > ${md5file} + log_it "Patched scripts using $patchfile" + touch /var/cache/cloud/patch.required + fi + + if [ -f $privkey ]; then + cp -f $privkey /root/.ssh/ + chmod go-rwx /root/.ssh/authorized_keys + fi + patched=true + break fi - if [ -f $privkey ]; then - cp -f $privkey /root/.ssh/ - chmod go-rwx /root/.ssh/authorized_keys - fi - fi + sleep 2 + retry=$(($retry-1)) + log_it "Could not find patch file, retrying" + done + if [ $retry -eq 0 ] && [ "$patched" == "false" ]; then + return 2 + fi return 0 } +cleanup() { + rm -rf /home/cloud/agent.zip + rm -rf /home/cloud/cloud-scripts.tgz +} + start() { log_it "Executing cloud-early-config" @@ -99,6 +107,7 @@ start() { patch sync /opt/cloud/bin/setup/bootstrap.sh + cleanup log_it "Finished setting up systemvm" exit 0 diff --git a/systemvm/debian/opt/cloud/bin/setup/common.sh b/systemvm/debian/opt/cloud/bin/setup/common.sh index 60b88754bee3..7f3d85717791 100755 --- a/systemvm/debian/opt/cloud/bin/setup/common.sh +++ b/systemvm/debian/opt/cloud/bin/setup/common.sh @@ -15,7 +15,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. - +set -x PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" . /lib/lsb/init-functions diff --git a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh index 3f00f3da43a1..ec45b7ffc942 100755 --- a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh +++ b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh @@ -25,7 +25,6 @@ setup_console_proxy() { echo "haproxy dnsmasq apache2 nfs-common portmap" > /var/cache/cloud/disabled_svcs mkdir -p /var/log/cloud - setup_common eth0 eth1 eth2 setup_system_rfc1918_internal log_it "Setting up entry in hosts" @@ -33,17 +32,6 @@ setup_console_proxy() { public_ip=`getPublicIp` echo "$public_ip $NAME" >> /etc/hosts - log_it "Applying iptables rules" - cp /etc/iptables/iptables-consoleproxy /etc/iptables/rules.v4 - - log_it "Configuring sshd" - local hyp=$HYPERVISOR - if [ "$hyp" == "vmware" ] || [ "$hyp" == "hyperv" ]; then - setup_sshd $ETH1_IP "eth1" - else - setup_sshd $ETH0_IP "eth0" - fi - disable_rpfilter enable_fwding 0 enable_irqbalance 0 diff --git a/systemvm/debian/opt/cloud/bin/setup/dhcpsrvr.sh b/systemvm/debian/opt/cloud/bin/setup/dhcpsrvr.sh index 9161aeb37ee4..0b9e8a7c5cc6 100755 --- a/systemvm/debian/opt/cloud/bin/setup/dhcpsrvr.sh +++ b/systemvm/debian/opt/cloud/bin/setup/dhcpsrvr.sh @@ -25,7 +25,7 @@ dhcpsrvr_svcs() { setup_dhcpsrvr() { log_it "Setting up dhcp server system vm" - setup_common eth0 eth1 +# setup_common eth0 eth1 setup_dnsmasq setup_apache2 $ETH0_IP @@ -36,18 +36,16 @@ setup_dhcpsrvr() { enable_irqbalance 0 enable_fwding 0 - cp /etc/iptables/iptables-router /etc/iptables/rules.v4 - #Only allow DNS service for current network sed -i "s/-A INPUT -i eth0 -p udp -m udp --dport 53 -j ACCEPT/-A INPUT -i eth0 -p udp -m udp --dport 53 -s $DHCP_RANGE\/$CIDR_SIZE -j ACCEPT/g" /etc/iptables/rules.v4 sed -i "s/-A INPUT -i eth0 -p tcp -m tcp --dport 53 -j ACCEPT/-A INPUT -i eth0 -p tcp -m tcp --dport 53 -s $DHCP_RANGE\/$CIDR_SIZE -j ACCEPT/g" /etc/iptables/rules.v4 - if [ "$SSHONGUEST" == "true" ] - then - setup_sshd $ETH0_IP "eth0" - else - setup_sshd $ETH1_IP "eth1" - fi +# if [ "$SSHONGUEST" == "true" ] +# then +# setup_sshd $ETH0_IP "eth0" +# else +# setup_sshd $ETH1_IP "eth1" +# fi } dhcpsrvr_svcs diff --git a/systemvm/debian/opt/cloud/bin/setup/elbvm.sh b/systemvm/debian/opt/cloud/bin/setup/elbvm.sh index ae16b4bcb7c4..52132ccea96f 100755 --- a/systemvm/debian/opt/cloud/bin/setup/elbvm.sh +++ b/systemvm/debian/opt/cloud/bin/setup/elbvm.sh @@ -25,20 +25,11 @@ elbvm_svcs() { setup_elbvm() { log_it "Setting up Elastic Load Balancer system vm" - setup_common eth0 eth1 sed -i /$NAME/d /etc/hosts public_ip=$ETH2_IP [ "$ETH2_IP" == "0.0.0.0" ] || [ "$ETH2_IP" == "" ] && public_ip=$ETH0_IP echo "$public_ip $NAME" >> /etc/hosts - cp /etc/iptables/iptables-elbvm /etc/iptables/rules.v4 - if [ "$SSHONGUEST" == "true" ] - then - setup_sshd $ETH0_IP "eth0" - else - setup_sshd $ETH1_IP "eth1" - fi - enable_fwding 0 enable_irqbalance 0 } diff --git a/systemvm/debian/opt/cloud/bin/setup/ilbvm.sh b/systemvm/debian/opt/cloud/bin/setup/ilbvm.sh index ac801b200e6a..83cc85525d5a 100755 --- a/systemvm/debian/opt/cloud/bin/setup/ilbvm.sh +++ b/systemvm/debian/opt/cloud/bin/setup/ilbvm.sh @@ -25,7 +25,7 @@ ilbvm_svcs() { setup_ilbvm() { log_it "Setting up Internal Load Balancer system vm" - setup_common eth0 eth1 +# setup_common eth0 eth1 #eth0 = guest network, eth1=control network sed -i /$NAME/d /etc/hosts diff --git a/systemvm/debian/opt/cloud/bin/setup/init.sh b/systemvm/debian/opt/cloud/bin/setup/init.sh new file mode 100644 index 000000000000..5923b351d1c2 --- /dev/null +++ b/systemvm/debian/opt/cloud/bin/setup/init.sh @@ -0,0 +1,217 @@ +#!/bin/bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +set -x +PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" +CMDLINE=/var/cache/cloud/cmdline + +hypervisor() { + if [ -d /proc/xen ]; then + mount -t xenfs none /proc/xen + $(dmesg | grep -q "Xen HVM") + if [ $? -eq 0 ]; then # 1=PV,0=HVM + echo "xen-hvm" && return 0 + else + echo "xen-pv" && return 0 + fi + fi + + [ -x /usr/sbin/virt-what ] && local facts=( $(virt-what) ) + if [ "$facts" != "" ]; then + # Xen HVM is recognized as Hyperv when Viridian extensions are enabled + if [ "${facts[-1]}" == "xen-domU" ] && [ "${facts[0]}" == "hyperv" ]; then + echo "xen-hvm" && return 0 + else + echo ${facts[-1]} && return 0 + fi + fi + + grep -q QEMU /proc/cpuinfo && echo "kvm" && return 0 + grep -q QEMU /var/log/messages && echo "kvm" && return 0 + + vmware-checkvm &> /dev/null && echo "vmware" && return 0 + + echo "unknown" && return 1 +} + +config_guest() { + [ ! -d /proc/xen ] && sed -i 's/^vc/#vc/' /etc/inittab && telinit q + [ -d /proc/xen ] && sed -i 's/^#vc/vc/' /etc/inittab && telinit q + + systemctl daemon-reload + + case $HYPERVISOR in + xen-pv|xen-domU) + systemctl stop ntpd + systemctl disable ntpd + systemctl enable xe-daemon + systemctl start xe-daemon + + cat /proc/cmdline > $CMDLINE + sed -i "s/%/ /g" $CMDLINE + ;; + xen-hvm) + systemctl stop ntpd + systemctl disable ntpd + systemctl enable xe-daemon + systemctl start xe-daemon + + if [ ! -f /usr/bin/xenstore-read ]; then + log_it "ERROR: xentools not installed, cannot found xenstore-read" && exit 5 + fi + /usr/bin/xenstore-read vm-data/cloudstack/init > $CMDLINE + sed -i "s/%/ /g" $CMDLINE + ;; + kvm) + # Configure kvm hotplug support + if grep -E 'CONFIG_HOTPLUG_PCI=y|CONFIG_HOTPLUG_PCI_ACPI=y' /boot/config-`uname -r`; then + log_it "acpiphp and pci_hotplug module already compiled in" + else + modprobe acpiphp 2> /dev/null && log_it "acpiphp module loaded" || true + modprobe pci_hotplug 2> /dev/null && log_it "pci_hotplug module loaded" || true + fi + + sed -i -e "/^s0:2345:respawn.*/d" /etc/inittab + sed -i -e "/6:23:respawn/a\s0:2345:respawn:/sbin/getty -L 115200 ttyS0 vt102" /etc/inittab + systemctl enable qemu-guest-agent + systemctl start qemu-guest-agent + + # Wait for $CMDLINE file to be written by the qemu-guest-agent + for i in {1..60}; do + if [ -s $CMDLINE ]; then + log_it "Received a new non-empty cmdline file from qemu-guest-agent" + # Remove old configuration files in /etc/cloudstack if VR is booted from cloudstack + rm -rf /etc/cloudstack/*.json + log_it "Booting from cloudstack, remove old configuration files in /etc/cloudstack/" + break + fi + sleep 1 + done + if [ ! -s $CMDLINE ]; then + log_it "Failed to receive the cmdline file via the qemu-guest-agent" + fi + ;; + vmware) + # system time sync'd with host via vmware tools + systemctl stop ntpd + systemctl disable ntpd + systemctl enable open-vm-tools + systemctl start open-vm-tools + + vmtoolsd --cmd 'machine.id.get' > $CMDLINE + ;; + virtualpc|hyperv) + # Hyper-V is recognized as virtualpc hypervisor type. Boot args are passed using KVP Daemon + systemctl enable hyperv-daemons.hv-fcopy-daemon.service hyperv-daemons.hv-kvp-daemon.service hyperv-daemons.hv-vss-daemon.service + systemctl start hyperv-daemons.hv-fcopy-daemon.service hyperv-daemons.hv-kvp-daemon.service hyperv-daemons.hv-vss-daemon.service + sleep 5 + cp -f /var/opt/hyperv/.kvp_pool_0 $CMDLINE + cat /dev/null > /var/opt/hyperv/.kvp_pool_0 + ;; + virtualbox) + # Virtualbox is used to test the virtual router + # get the commandline from a dmistring (yes, hacky!) + dmidecode | grep cmdline | sed 's/^.*cmdline://' > $CMDLINE + RV=$? + if [ $RV -ne 0 ] ; then + log_it "Failed to get cmdline from a virtualbox dmi property" + fi + ;; + esac + + if [ -f /mnt/cmdline ]; then + cat /mnt/cmdline > $CMDLINE + fi + + # Find and export guest type + export TYPE=$(grep -Po 'type=\K[a-zA-Z]*' $CMDLINE) +} + +setup_interface_sshd() { + + if [ "$TYPE" != "cksnode" ]; then + log_it "Applying iptables rules" + if [ "$TYPE" != "dhcpsrvr" ]; then + cp /etc/iptables/iptables-$TYPE /etc/iptables/rules.v4 + else + cp /etc/iptables/iptables-router /etc/iptables/rules.v4 + fi + fi + + if [ "$TYPE" == "consoleproxy" ] || [ "$TYPE" == "secstorage" ]; then + setup_common eth0 eth1 eth2 + log_it "Configuring sshd" + local hyp=$HYPERVISOR + if [ "$hyp" == "vmware" ] || [ "$hyp" == "hyperv" ]; then + setup_sshd $ETH1_IP "eth1" + else + setup_sshd $ETH0_IP "eth0" + fi + + elif [ "$TYPE" == "router" ]; then + if [ -n "$ETH2_IP" ]; then + setup_common eth0 eth1 eth2 + + if [ -n "$EXTRA_PUBNICS" ]; then + for ((i = 3; i < 3 + $EXTRA_PUBNICS; i++)); do + setup_interface "$i" "0.0.0.0" "255.255.255.255" $GW "force" + done + fi + else + setup_common eth0 eth1 + if [ -n "$EXTRA_PUBNICS" ]; then + for ((i = 2; i < 2 + $EXTRA_PUBNICS; i++)); do + setup_interface "$i" "0.0.0.0" "255.255.255.255" $GW "force" + done + fi + fi + setup_sshd $ETH1_IP "eth1" + + elif [ "$TYPE" == "vpcrouter" ]; then + setup_interface "0" $ETH0_IP $ETH0_MASK $GW + setup_sshd $ETH0_IP "eth0" + + elif [ "$TYPE" == "ilbvm" ]; then + setup_common eth0 eth1 + setup_sshd $ETH1_IP "eth1" + + elif [ "$TYPE" == "elbvm" ] || [ "$TYPE" == "dhcpsrvr"]; then + setup_common eth0 eth1 + if [ "$SSHONGUEST" == "true" ]; then + setup_sshd $ETH0_IP "eth0" + else + setup_sshd $ETH1_IP "eth1" + fi + elif [ "$TYPE" == "cksnode" ]; then + setup_common eth0 + fi + + systemctl restart systemd-journald + # Patch known systemd/sshd memory leak - https://github.com/systemd/systemd/issues/8015#issuecomment-476160981 + echo '@include null' >> /etc/pam.d/systemd-user + # Enable and Start SSH + systemctl enable --now --no-block ssh +} + +export HYPERVISOR=$(hypervisor) +[ $? -ne 0 ] && log_it "Failed to detect hypervisor type, bailing out" && exit 10 +log_it "Starting guest services for $HYPERVISOR" + +config_guest +source /opt/cloud/bin/setup/common.sh +setup_interface_sshd \ No newline at end of file diff --git a/systemvm/debian/opt/cloud/bin/setup/postinit.sh b/systemvm/debian/opt/cloud/bin/setup/postinit.sh index 04929302f513..ba5c394d9f24 100755 --- a/systemvm/debian/opt/cloud/bin/setup/postinit.sh +++ b/systemvm/debian/opt/cloud/bin/setup/postinit.sh @@ -23,17 +23,11 @@ log_it() { log_action_msg "$@" } -# Eject cdrom if any -CMDLINE=/var/cache/cloud/cmdline -export TYPE=$(grep -Po 'type=\K[a-zA-Z]*' $CMDLINE) -if [ "$TYPE" != "cksnode" ]; then - eject || true -fi - # Restart journald for setting changes to apply systemctl restart systemd-journald -TYPE=$(grep -Po 'type=\K[a-zA-Z]*' /var/cache/cloud/cmdline) +CMDLINE=/var/cache/cloud/cmdline +TYPE=$(grep -Po 'type=\K[a-zA-Z]*' $CMDLINE) if [ "$TYPE" == "router" ] || [ "$TYPE" == "vpcrouter" ] || [ "$TYPE" == "dhcpsrvr" ] then if [ -x /opt/cloud/bin/update_config.py ] @@ -71,10 +65,4 @@ then ip6tables-restore < $ipv6 fi -# Patch known systemd/sshd memory leak - https://github.com/systemd/systemd/issues/8015#issuecomment-476160981 -echo '@include null' >> /etc/pam.d/systemd-user - -# Enable and Start SSH -systemctl enable --now --no-block ssh - date > /var/cache/cloud/boot_up_done diff --git a/systemvm/debian/opt/cloud/bin/setup/router.sh b/systemvm/debian/opt/cloud/bin/setup/router.sh index e8f6edf0ceb5..d7113c493028 100755 --- a/systemvm/debian/opt/cloud/bin/setup/router.sh +++ b/systemvm/debian/opt/cloud/bin/setup/router.sh @@ -43,23 +43,6 @@ setup_router() { oldmd5= [ -f "/etc/udev/rules.d/70-persistent-net.rules" ] && oldmd5=$(md5sum "/etc/udev/rules.d/70-persistent-net.rules" | awk '{print $1}') - if [ -n "$ETH2_IP" ]; then - setup_common eth0 eth1 eth2 - - if [ -n "$EXTRA_PUBNICS" ]; then - for ((i = 3; i < 3 + $EXTRA_PUBNICS; i++)); do - setup_interface "$i" "0.0.0.0" "255.255.255.255" $GW "force" - done - fi - else - setup_common eth0 eth1 - if [ -n "$EXTRA_PUBNICS" ]; then - for ((i = 2; i < 2 + $EXTRA_PUBNICS; i++)); do - setup_interface "$i" "0.0.0.0" "255.255.255.255" $GW "force" - done - fi - fi - log_it "Checking udev NIC assignment order changes" if [ "$NIC_MACS" != "" ] then @@ -88,8 +71,6 @@ setup_router() { enable_fwding 1 enable_rpsrfs 1 enable_passive_ftp 1 - cp /etc/iptables/iptables-router /etc/iptables/rules.v4 - setup_sshd $ETH1_IP "eth1" # Only allow DNS service for current network sed -i "s/-A INPUT -i eth0 -p udp -m udp --dport 53 -j ACCEPT/-A INPUT -i eth0 -p udp -m udp --dport 53 -s $DHCP_RANGE\/$CIDR_SIZE -j ACCEPT/g" /etc/iptables/rules.v4 diff --git a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh index 13ed5c5d0ae0..3b21ed5cae17 100755 --- a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh +++ b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh @@ -25,7 +25,6 @@ setup_secstorage() { echo "conntrackd keepalived haproxy dnsmasq" > /var/cache/cloud/disabled_svcs mkdir -p /var/log/cloud - setup_common eth0 eth1 eth2 setup_storage_network setup_system_rfc1918_internal @@ -37,14 +36,6 @@ setup_secstorage() { log_it "Applying iptables rules" cp /etc/iptables/iptables-secstorage /etc/iptables/rules.v4 - log_it "Configuring sshd" - local hyp=$HYPERVISOR - if [ "$hyp" == "vmware" ] || [ "$hyp" == "hyperv" ]; then - setup_sshd $ETH1_IP "eth1" - else - setup_sshd $ETH0_IP "eth0" - fi - log_it "Configuring apache2" setup_apache2 $ETH2_IP diff --git a/systemvm/debian/opt/cloud/bin/setup/vpcrouter.sh b/systemvm/debian/opt/cloud/bin/setup/vpcrouter.sh index f97fb161f47f..ba4af90d9b6c 100755 --- a/systemvm/debian/opt/cloud/bin/setup/vpcrouter.sh +++ b/systemvm/debian/opt/cloud/bin/setup/vpcrouter.sh @@ -29,7 +29,6 @@ setup_vpcrouter() { auto lo eth0 iface lo inet loopback EOF - setup_interface "0" $ETH0_IP $ETH0_MASK $GW echo $NAME > /etc/hostname echo 'AVAHI_DAEMON_DETECT_LOCAL=0' > /etc/default/avahi-daemon @@ -86,7 +85,7 @@ EOF enable_fwding 1 enable_passive_ftp 1 cp /etc/iptables/iptables-vpcrouter /etc/iptables/rules.v4 - setup_sshd $ETH0_IP "eth0" +# setup_sshd $ETH0_IP "eth0" cp /etc/vpcdnsmasq.conf /etc/dnsmasq.conf cp /etc/cloud-nic.rules /etc/udev/rules.d/cloud-nic.rules echo "" > /etc/dnsmasq.d/dhcphosts.txt diff --git a/systemvm/patch-sysvms.sh b/systemvm/patch-sysvms.sh new file mode 100644 index 000000000000..cf0b452f82ed --- /dev/null +++ b/systemvm/patch-sysvms.sh @@ -0,0 +1,108 @@ +#!/bin/bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" +backupfolder=/tmp/bkpup_live_patch +logfile="/var/log/livepatchsystemvm.log" +newpath="/home/cloud/" +CMDLINE=/var/cache/cloud/cmdline +md5file=/var/cache/cloud/cloud-scripts-signature +svcfile=/var/cache/cloud/enabled_svcs +TYPE=$(grep -Po 'type=\K[a-zA-Z]*' $CMDLINE) +patchfailed=0 + + +backup_old_package() { + mkdir -p $backupfolder + echo "Backing up keystore file and certificates" > $logfile + mkdir -p $backupfolder/conf + cp -r /usr/local/cloud/systemvm/conf/* $backupfolder/conf + echo "Backing up agent package" >> $logfile + zip -r $backupfolder/agent.zip /usr/local/cloud/systemvm/* >> $logfile 2>&1 + cp $md5file $backupfolder + echo "Backing up cloud-scripts file" >> $logfile + tar -zcvf $backupfolder/cloud-scripts.tgz /etc/ /var/ /opt/ /root/ >> $logfile 2>&1 +} + +restore_backup() { + echo "Restoring cloud scripts" >> $logfile + tar -xvf $backupfolder/cloud-scripts.tar -C / >> $logfile 2>&1 + echo "Restoring agent package" >> $logfile + unzip $backupfolder/agent.zip -d /usr/local/cloud/systemvm/ >> $logfile 2>&1 + echo "Restore keystore file and certificates" + mkdir -p "/usr/local/cloud/systemvm/conf/" + cp -r $backupfolder/conf/* /usr/local/cloud/systemvm/conf/ + restart_services + cp $backupfolder/cloud-scripts-signature $md5file +} + +update_checksum() { + newmd5=$(md5sum $1 | awk '{print $1}') + echo "checksum: " ${newmd5} >> $logfile + echo ${newmd5} > ${md5file} +} + +restart_services() { + systemctl daemon-reload + while IFS= read -r line + do + echo "$line" + systemctl restart "$line" + sleep 5 + systemctl is-active --quiet "$line" + if [ $? -gt 0 ]; then + echo "Failed to start "$line" service. Patch Failed. Restoring backup" >> $logfile + restore_backup + patchfailed=1 + break + fi + done < "$svcfile" +} + +cleanup_systemVM() { + rm -rf $backupfolder + rm -rf "$newpath""cloud-scripts.tgz" "$newpath""agent.zip" "$newpath""patch-sysvms.sh" +} + +patch_systemvm() { + rm -rf /usr/local/cloud/systemvm + mkdir -p /usr/local/cloud/systemvm + echo "All" | unzip $newpath/agent.zip -d /usr/local/cloud/systemvm >> $logfile 2>&1 + find /usr/local/cloud/systemvm/ -name \*.sh | xargs chmod 555 + + echo "Extracting cloud scripts" >> $logfile + tar -xvf $newpath/cloud-scripts.tgz -C / >> $logfile 2>&1 + + if [ -f $backupfolder/conf/cloud.jks ]; then + cp -r $backupfolder/conf/* /usr/local/cloud/systemvm/conf/ + echo "Restored keystore file and certs using backup" >> $logfile + fi + + update_checksum $newpath/cloud-scripts.tgz + + if [ "$TYPE" == "consoleproxy" ] || [ "$TYPE" == "secstorage" ] || [[ "$TYPE" == *router ]]; then + restart_services + fi +} + + +backup_old_package +patch_systemvm +cleanup_systemVM + +exit $patchfailed diff --git a/systemvm/pom.xml b/systemvm/pom.xml index 7fe4ae8a5e4e..929f948abd1d 100644 --- a/systemvm/pom.xml +++ b/systemvm/pom.xml @@ -88,6 +88,12 @@ agent.zip + + ${basedir} + + patch-sysvms.sh + + diff --git a/tools/appliance/build.sh b/tools/appliance/build.sh index 1c83f9aba510..79de31a9adeb 100755 --- a/tools/appliance/build.sh +++ b/tools/appliance/build.sh @@ -349,10 +349,10 @@ function main() { # process the disk at dist kvm_export - ovm_export - xen_server_export - vmware_export - hyperv_export +# ovm_export +# xen_server_export +# vmware_export +# hyperv_export rm -f "dist/${appliance}" cd dist && chmod +r * && cd .. cd dist && md5sum * > md5sum.txt && cd .. diff --git a/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh b/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh index db3eec5cb40c..8cdfce787534 100644 --- a/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh +++ b/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh @@ -68,6 +68,7 @@ function install_cloud_scripts() { chmod -x /etc/systemd/system/* || true systemctl daemon-reload + systemctl enable cloud-preinit systemctl enable cloud-early-config systemctl enable cloud-postinit } diff --git a/tools/appliance/systemvmtemplate/template.json b/tools/appliance/systemvmtemplate/template.json index bd932bf6cdef..46fdbc90a750 100644 --- a/tools/appliance/systemvmtemplate/template.json +++ b/tools/appliance/systemvmtemplate/template.json @@ -27,8 +27,8 @@ "format": "qcow2", "headless": true, "http_directory": "http", - "iso_checksum": "sha512:5f6aed67b159d7ccc1a90df33cc8a314aa278728a6f50707ebf10c02e46664e383ca5fa19163b0a1c6a4cb77a39587881584b00b45f512b4a470f1138eaa1801", - "iso_url": "https://cdimage.debian.org/debian-cd/11.0.0/amd64/iso-cd/debian-11.0.0-amd64-netinst.iso", + "iso_checksum": "sha512:02257c3ec27e45d9f022c181a69b59da67e5c72871cdb4f9a69db323a1fad58093f2e69702d29aa98f5f65e920e0b970d816475a5a936e1f3bf33832257b7e92", + "iso_url": "https://cdimage.debian.org/debian-cd/11.1.0/amd64/iso-cd/debian-11.1.0-amd64-netinst.iso", "net_device": "virtio-net", "output_directory": "../dist", "qemuargs": [ diff --git a/utils/src/main/java/com/cloud/utils/EncryptionUtil.java b/utils/src/main/java/com/cloud/utils/EncryptionUtil.java index b82842e947b6..ff791a3f5226 100644 --- a/utils/src/main/java/com/cloud/utils/EncryptionUtil.java +++ b/utils/src/main/java/com/cloud/utils/EncryptionUtil.java @@ -18,7 +18,12 @@ */ package com.cloud.utils; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.io.UnsupportedEncodingException; +import java.nio.file.Files; +import java.nio.file.Paths; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -26,6 +31,7 @@ import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.digest.DigestUtils; import org.apache.log4j.Logger; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; @@ -70,4 +76,14 @@ public static String generateSignature(String data, String key) { throw new CloudRuntimeException("unable to generate signature", e); } } + + public static String calculateChecksum(File file) { + try (InputStream is = Files.newInputStream(Paths.get(file.getPath()))) { + return DigestUtils.md5Hex(is); + } catch (IOException e) { + String errMsg = "Failed to calculate template checksum"; + s_logger.error(errMsg, e); + throw new CloudRuntimeException(errMsg, e); + } + } } diff --git a/utils/src/main/java/com/cloud/utils/ssh/SshHelper.java b/utils/src/main/java/com/cloud/utils/ssh/SshHelper.java index bce61fd4629c..7a73e8675a70 100644 --- a/utils/src/main/java/com/cloud/utils/ssh/SshHelper.java +++ b/utils/src/main/java/com/cloud/utils/ssh/SshHelper.java @@ -52,6 +52,12 @@ public static void scpTo(String host, int port, String user, File pemKeyFile, St scpTo(host, port, user, pemKeyFile, password, remoteTargetDirectory, localFile, fileMode, DEFAULT_CONNECT_TIMEOUT, DEFAULT_KEX_TIMEOUT); } + public static void scpTo(String host, int port, String user, File pemKeyFile, String password, String remoteTargetDirectory, String[] localFiles, String fileMode) + throws Exception { + + scpTo(host, port, user, pemKeyFile, password, remoteTargetDirectory, localFiles, fileMode, DEFAULT_CONNECT_TIMEOUT, DEFAULT_KEX_TIMEOUT); + } + public static void scpTo(String host, int port, String user, File pemKeyFile, String password, String remoteTargetDirectory, byte[] data, String remoteFileName, String fileMode) throws Exception { @@ -118,6 +124,42 @@ public static void scpTo(String host, int port, String user, File pemKeyFile, St } } + public static void scpTo(String host, int port, String user, File pemKeyFile, String password, String remoteTargetDirectory, String[] localFiles, String fileMode, + int connectTimeoutInMs, int kexTimeoutInMs) throws Exception { + + com.trilead.ssh2.Connection conn = null; + com.trilead.ssh2.SCPClient scpClient = null; + + try { + conn = new com.trilead.ssh2.Connection(host, port); + conn.connect(null, connectTimeoutInMs, kexTimeoutInMs); + + if (pemKeyFile == null) { + if (!conn.authenticateWithPassword(user, password)) { + String msg = "Failed to authentication SSH user " + user + " on host " + host; + s_logger.error(msg); + throw new Exception(msg); + } + } else { + if (!conn.authenticateWithPublicKey(user, pemKeyFile, password)) { + String msg = "Failed to authentication SSH user " + user + " on host " + host; + s_logger.error(msg); + throw new Exception(msg); + } + } + + scpClient = conn.createSCPClient(); + + if (fileMode != null) + scpClient.put(localFiles, remoteTargetDirectory, fileMode); + else + scpClient.put(localFiles, remoteTargetDirectory); + } finally { + if (conn != null) + conn.close(); + } + } + public static void scpTo(String host, int port, String user, File pemKeyFile, String password, String remoteTargetDirectory, byte[] data, String remoteFileName, String fileMode, int connectTimeoutInMs, int kexTimeoutInMs) throws Exception { From 50c59bc40102c7d3871251c7bc5877f60ea60452 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Tue, 14 Dec 2021 13:16:09 +0530 Subject: [PATCH 02/68] The following commit: - refactors logic added to support SystemVM deployment on KVM - Adds support to copy specific files (required for patching) to the hosts on Xenserver - Modifies vmops method - createFileInDomr to take cleanup param - Adds configuratble sleep param to CitrixResourceBase::connect() used to verify if telnet to specifc port is possible (if sleep is 0, then default to _sleep = 10000ms) - Adds Command/Answer for patch systemVMs on XenServer/Xcp --- .../com/cloud/resource/ServerResource.java | 8 ++ .../cloud/resource/ServerResourceBase.java | 12 ++ .../resource/LibvirtComputingResource.java | 5 - .../LibvirtPatchSystemVmCommandWrapper.java | 35 +----- .../wrapper/LibvirtStartCommandWrapper.java | 12 +- .../resource/CitrixResourceBase.java | 45 ++++++-- .../xenbase/CitrixCheckSshCommandWrapper.java | 2 +- .../CitrixPatchSystemVmCommandWrapper.java | 106 ++++++++++++++++++ .../CitrixRebootRouterCommandWrapper.java | 2 +- .../xenbase/CitrixStartCommandWrapper.java | 24 ++++ scripts/vm/hypervisor/xenserver/vmops | 4 +- scripts/vm/hypervisor/xenserver/xcposs/patch | 3 + .../vm/hypervisor/xenserver/xcpserver/patch | 5 +- .../vm/hypervisor/xenserver/xenserver56/patch | 3 + .../hypervisor/xenserver/xenserver56fp1/patch | 3 + .../vm/hypervisor/xenserver/xenserver60/patch | 3 + .../vm/hypervisor/xenserver/xenserver62/patch | 3 + .../vm/hypervisor/xenserver/xenserver65/patch | 3 + tools/appliance/build.sh | 6 +- .../main/java/com/cloud/utils/FileUtil.java | 23 ++++ 20 files changed, 244 insertions(+), 63 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java diff --git a/core/src/main/java/com/cloud/resource/ServerResource.java b/core/src/main/java/com/cloud/resource/ServerResource.java index 16ac00ed176b..5571f33bb8a3 100644 --- a/core/src/main/java/com/cloud/resource/ServerResource.java +++ b/core/src/main/java/com/cloud/resource/ServerResource.java @@ -27,11 +27,19 @@ import com.cloud.host.Host; import com.cloud.utils.component.Manager; +import java.io.File; + /** * ServerResource is a generic container to execute commands sent */ public interface ServerResource extends Manager { + String[] srcFiles = new String[] { "agent.zip", "cloud-scripts.tgz" }; + String[] newSrcFiles = new String[] { "agent.zip", "cloud-scripts.tgz", "patch-sysvms.sh" }; + + String SSHKEYSPATH = "/root/.ssh"; + String SSHPRVKEYPATH = SSHKEYSPATH + File.separator + "id_rsa.cloud"; + /** * @return Host.Type type of the computing server we have. */ diff --git a/core/src/main/java/com/cloud/resource/ServerResourceBase.java b/core/src/main/java/com/cloud/resource/ServerResourceBase.java index f68bcf409ef3..80057779e249 100644 --- a/core/src/main/java/com/cloud/resource/ServerResourceBase.java +++ b/core/src/main/java/com/cloud/resource/ServerResourceBase.java @@ -19,6 +19,7 @@ package com.cloud.resource; +import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; import java.net.NetworkInterface; @@ -32,6 +33,8 @@ import javax.naming.ConfigurationException; +import com.cloud.utils.EncryptionUtil; +import com.cloud.utils.exception.CloudRuntimeException; import org.apache.log4j.Logger; import com.cloud.agent.IAgentControl; @@ -306,4 +309,13 @@ public boolean start() { public boolean stop() { return true; } + + public String calculateCurrentChecksum(String name) { + String cloudScriptsPath = Script.findScript("", "vms/cloud-scripts.tgz"); + if (cloudScriptsPath == null) { + throw new CloudRuntimeException(String.format("Unable to find cloudScripts path, cannot update SystemVM %s", name)); + } + String md5sum = EncryptionUtil.calculateChecksum(new File(cloudScriptsPath)); + return md5sum; + } } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index a3257f9967bd..e7cdfbb925f7 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -281,9 +281,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv public static final String RESIZE_NOTIFY_ONLY = "NOTIFYONLY"; public static final String BASEPATH = "/usr/share/cloudstack-common/vms/"; - public static String[] srcFiles = new String[] { "agent.zip", "cloud-scripts.tgz" }; - public static String[] newSrcFiles = new String[] { "agent.zip", "cloud-scripts.tgz", "patch-sysvms.sh" }; - private String _modifyVlanPath; private String _versionstringpath; private String _patchScriptPath; @@ -309,8 +306,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv private static final int NUMMEMSTATS =2; private KVMHAMonitor _monitor; - public static final String SSHKEYSPATH = "/root/.ssh"; - public static final String SSHPRVKEYPATH = SSHKEYSPATH + File.separator + "id_rsa.cloud"; public static final String SSHPUBKEYPATH = SSHKEYSPATH + File.separator + "id_rsa.pub.cloud"; public static final String DEFAULTDOMRSSHPORT = "3922"; diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java index 392ccb6e6584..5fac33ebec22 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java @@ -24,19 +24,15 @@ import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource; import com.cloud.resource.CommandWrapper; import com.cloud.resource.ResourceWrapper; -import com.cloud.utils.EncryptionUtil; import com.cloud.utils.ExecutionResult; +import com.cloud.utils.FileUtil; import com.cloud.utils.Pair; import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.script.Script; import com.cloud.utils.ssh.SshHelper; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import java.io.File; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; @ResourceWrapper(handles = PatchSystemVmCommand.class) public class LibvirtPatchSystemVmCommandWrapper extends CommandWrapper { @@ -51,7 +47,7 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR ExecutionResult result; try { result = getSystemVmVersionAndChecksum(serverResource, controlIp); - scpPatchFiles(controlIp); + FileUtil.scpPatchFiles(controlIp, "/home/cloud", sshPort, pemFile, serverResource.newSrcFiles, LibvirtComputingResource.BASEPATH); } catch (CloudRuntimeException e) { return new PatchSystemVmAnswer(cmd, e.getMessage()); } @@ -63,7 +59,7 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR } String scriptChecksum = lines[1].trim(); - String checksum = calculateCurrentChecksum(sysVMName).trim(); + String checksum = serverResource.calculateCurrentChecksum(sysVMName).trim(); if (!StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum)) { if (!cmd.isForced()) { @@ -87,15 +83,6 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR return new PatchSystemVmAnswer(cmd, patchResult.second()); } - private String calculateCurrentChecksum(String name) { - String cloudScriptsPath = Script.findScript("", "vms/cloud-scripts.tgz"); - if (cloudScriptsPath == null) { - throw new CloudRuntimeException(String.format("Unable to find cloudScripts path, cannot update SystemVM %s", name)); - } - String md5sum = EncryptionUtil.calculateChecksum(new File(cloudScriptsPath)); - return md5sum; - } - private ExecutionResult getSystemVmVersionAndChecksum(LibvirtComputingResource serverResource, String controlIp) { ExecutionResult result; try { @@ -112,21 +99,5 @@ private ExecutionResult getSystemVmVersionAndChecksum(LibvirtComputingResource s } return result; } - - private void scpPatchFiles(String controlIp) { - try { - List srcFiles = Arrays.asList(LibvirtComputingResource.newSrcFiles); - srcFiles = srcFiles.stream() - .map(file -> LibvirtComputingResource.BASEPATH + file) // Using Lambda notation to update the entries - .collect(Collectors.toList()); - String[] newSrcFiles = srcFiles.toArray(new String[0]); - SshHelper.scpTo(controlIp, sshPort, "root", pemFile, null, - "/home/cloud/", newSrcFiles, "0755"); - } catch (Exception e) { - String errMsg = "Failed to scp files to system VM"; - s_logger.error(errMsg, e); - throw new CloudRuntimeException(errMsg, e); - } - } } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java index b95c163e7081..2ac8bf798482 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java @@ -21,11 +21,8 @@ import java.io.File; import java.net.URISyntaxException; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; -import com.cloud.utils.ssh.SshHelper; +import com.cloud.utils.FileUtil; import org.apache.log4j.Logger; import org.libvirt.Connect; import org.libvirt.DomainInfo.DomainState; @@ -122,13 +119,8 @@ public Answer execute(final StartCommand command, final LibvirtComputingResource } try { - List srcFiles = Arrays.asList(LibvirtComputingResource.srcFiles); - srcFiles = srcFiles.stream() - .map(file -> LibvirtComputingResource.BASEPATH + file) - .collect(Collectors.toList()); File pemFile = new File(LibvirtComputingResource.SSHPRVKEYPATH); - SshHelper.scpTo(controlIp, 3922, "root", pemFile, null, - "/home/cloud/", srcFiles.toArray(new String[0]), "0755"); + FileUtil.scpPatchFiles(controlIp, "/home/cloud", Integer.parseInt(LibvirtComputingResource.DEFAULTDOMRSSHPORT), pemFile, LibvirtComputingResource.newSrcFiles, LibvirtComputingResource.BASEPATH); // TODO: May want to remove this when cert patching logic is moved Thread.sleep(10000); } catch (Exception e) { diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java index c3987fd963f2..39dd0e59fedd 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java @@ -52,6 +52,7 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import com.cloud.resource.ServerResourceBase; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.diagnostics.CopyToSecondaryStorageAnswer; import org.apache.cloudstack.diagnostics.CopyToSecondaryStorageCommand; @@ -180,7 +181,7 @@ * before you do any changes in this code here. * */ -public abstract class CitrixResourceBase implements ServerResource, HypervisorResource, VirtualRouterDeployer { +public abstract class CitrixResourceBase extends ServerResourceBase implements ServerResource, HypervisorResource, VirtualRouterDeployer { /** * used to describe what type of resource a storage device is of */ @@ -216,6 +217,7 @@ public String toString() { private final static String VM_NAME_ISO_SUFFIX = "-ISO"; private final static String VM_FILE_ISO_SUFFIX = ".iso"; + public final static int DEFAULTDOMRSSHPORT = 3922; private static final XenServerConnectionPool ConnPool = XenServerConnectionPool.getInstance(); // static min values for guests on xenserver @@ -226,6 +228,7 @@ public String toString() { protected static final HashMap s_powerStatesTable; public static final String XS_TOOLS_ISO_AFTER_70 = "guest-tools.iso"; + public static final String BASEPATH = "/opt/xensource/packages/resources/"; static { s_powerStatesTable = new HashMap(); @@ -339,6 +342,11 @@ protected StorageSubsystemCommandHandler buildStorageHandler() { return new StorageSubsystemCommandHandlerBase(processor); } + @Override + protected String getDefaultScriptsDir() { + return null; + } + public String callHostPlugin(final Connection conn, final String plugin, final String cmd, final String... params) { final Map args = new HashMap(); String msg; @@ -904,11 +912,15 @@ public synchronized Network configureTunnelNetwork(final Connection conn, final } } - public String connect(final Connection conn, final String vmname, final String ipAddress) { - return connect(conn, vmname, ipAddress, 3922); + public String connect(final Connection conn, final String vmname, final String ipAddress, int sleep) { + return connect(conn, vmname, ipAddress, DEFAULTDOMRSSHPORT, sleep); } - public String connect(final Connection conn, final String vmName, final String ipAddress, final int port) { + public String connect(final Connection conn, final String vmName, final String ipAddress, final int port, int sleep) { + if (sleep == 0) { + sleep = _sleep; + } + for (int i = 0; i <= _retry; i++) { try { final Set vms = VM.getByNameLabel(conn, vmName); @@ -929,7 +941,7 @@ public String connect(final Connection conn, final String vmName, final String i return null; } try { - Thread.sleep(_sleep); + Thread.sleep(sleep); } catch (final InterruptedException e) { } } @@ -974,8 +986,25 @@ public ExecutionResult createFileInVR(final String routerIp, final String path, s_logger.warn("scp VR config file into host " + _host.getIp() + " failed with exception " + e.getMessage().toString()); } - final String rc = callHostPlugin(conn, "vmops", "createFileInDomr", "domrip", routerIp, "srcfilepath", hostPath + filename, "dstfilepath", path); - s_logger.debug("VR Config file " + filename + " got created in VR, ip " + routerIp + " with content \n" + content); + final String rc = callHostPlugin(conn, "vmops", "createFileInDomr", "domrip", routerIp, "srcfilepath", hostPath + filename, "dstfilepath", path, "cleanup", "true"); + s_logger.debug("VR Config file " + filename + " got created in VR, IP: " + routerIp + " with content \n" + content); + + return new ExecutionResult(rc.startsWith("succ#"), rc.substring(5)); + } + + public ExecutionResult copyPatchFilesToVR(final String routerIp, final String path) { + final Connection conn = getConnection(); + final String hostPath = "/opt/xensource/packages/resources/"; + String rc = ""; + for (String file: newSrcFiles) { + rc = callHostPlugin(conn, "vmops", "createFileInDomr", "domrip", routerIp, "srcfilepath", hostPath.concat(file), "dstfilepath", path, "cleanup", "false"); + if (rc.startsWith("fail#")) { + s_logger.error(String.format("Failed to scp file %s required for patching the systemVM", file)); + break; + } + } + + s_logger.debug("VR Config files at " + hostPath + " got created in VR, IP: " + routerIp); return new ExecutionResult(rc.startsWith("succ#"), rc.substring(5)); } @@ -4885,7 +4914,7 @@ public boolean setupServer(final Connection conn, final Host host) { throw new CloudRuntimeException("Unable to authenticate"); } - final String cmd = "mkdir -p /opt/cloud/bin /var/log/cloud"; + final String cmd = "mkdir -p /opt/cloud/bin /var/log/cloud /opt/xensource/packages/resources/"; if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) { throw new CloudRuntimeException("Cannot create directory /opt/cloud/bin on XenServer hosts"); } diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixCheckSshCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixCheckSshCommandWrapper.java index cf34a8fb30cd..ec7d844dfbc7 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixCheckSshCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixCheckSshCommandWrapper.java @@ -46,7 +46,7 @@ public Answer execute(final CheckSshCommand command, final CitrixResourceBase ci } try { - final String result = citrixResourceBase.connect(conn, command.getName(), privateIp, cmdPort); + final String result = citrixResourceBase.connect(conn, command.getName(), privateIp, cmdPort, 0); if (result != null) { return new CheckSshAnswer(command, "Can not ping System vm " + vmName + "due to:" + result); } diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java new file mode 100644 index 000000000000..e27381e694da --- /dev/null +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java @@ -0,0 +1,106 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.hypervisor.xenserver.resource.wrapper.xenbase; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.PatchSystemVmAnswer; +import com.cloud.agent.api.PatchSystemVmCommand; +import com.cloud.agent.api.routing.NetworkElementCommand; +import com.cloud.agent.resource.virtualnetwork.VRScripts; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.cloud.resource.ResourceWrapper; +import com.cloud.utils.ExecutionResult; +import com.cloud.utils.FileUtil; +import com.cloud.utils.Pair; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.ssh.SshHelper; +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Logger; + +import java.io.File; + +@ResourceWrapper(handles = PatchSystemVmCommand.class) +public class CitrixPatchSystemVmCommandWrapper extends CommandWrapper { + private static final Logger s_logger = Logger.getLogger(CitrixPatchSystemVmCommandWrapper.class); + private static int sshPort = CitrixResourceBase.DEFAULTDOMRSSHPORT; + private static File pemFile = new File(CitrixResourceBase.SSHPRVKEYPATH); + + @Override + public Answer execute(PatchSystemVmCommand command, CitrixResourceBase serverResource) { + final String controlIp = command.getAccessDetail(NetworkElementCommand.ROUTER_IP); + final String sysVMName = command.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + + + ExecutionResult result; + try { + result = getSystemVmVersionAndChecksum(serverResource, controlIp); + FileUtil.scpPatchFiles(controlIp, "/home/cloud", sshPort, pemFile, serverResource.newSrcFiles, CitrixResourceBase.BASEPATH); + } catch (CloudRuntimeException e) { + return new PatchSystemVmAnswer(command, e.getMessage()); + } + + final String[] lines = result.getDetails().split("&"); + // TODO: do we fail, or patch anyway?? + if (lines.length != 2) { + return new PatchSystemVmAnswer(command, result.getDetails()); + } + + String scriptChecksum = lines[1].trim(); + String checksum = serverResource.calculateCurrentChecksum(sysVMName).trim(); + + if (!StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum)) { + if (!command.isForced()) { + String msg = String.format("No change in the scripts checksum, not patching systemVM %s", sysVMName); + s_logger.info(msg); + return new PatchSystemVmAnswer(command, msg, lines[0], lines[1]); + } + } + Pair patchResult = null; + try { + patchResult = SshHelper.sshExecute(controlIp, sshPort, "root", + pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 60000); + } catch (Exception e) { + return new PatchSystemVmAnswer(command, e.getMessage()); + } + + if (patchResult.first()) { + return new PatchSystemVmAnswer(command, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], lines[1]); + } + return new PatchSystemVmAnswer(command, patchResult.second()); + + } + + private ExecutionResult getSystemVmVersionAndChecksum(CitrixResourceBase serverResource, String controlIp) { + ExecutionResult result; + try { + result = serverResource.executeInVR(controlIp, VRScripts.VERSION, null); + if (!result.isSuccess()) { + String errMsg = String.format("GetSystemVMVersionCmd on %s failed, message %s", controlIp, result.getDetails()); + s_logger.error(errMsg); + throw new CloudRuntimeException(errMsg); + } + } catch (final Exception e) { + final String msg = "GetSystemVMVersionCmd failed due to " + e; + s_logger.error(msg, e); + throw new CloudRuntimeException(msg, e); + } + return result; + } + + +} diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixRebootRouterCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixRebootRouterCommandWrapper.java index 236d8db3858a..a87458326e5b 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixRebootRouterCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixRebootRouterCommandWrapper.java @@ -40,7 +40,7 @@ public Answer execute(final RebootRouterCommand command, final CitrixResourceBas final Answer answer = wrapper.execute(rebootCommand, citrixResourceBase); if (answer.getResult()) { - final String cnct = citrixResourceBase.connect(conn, command.getVmName(), command.getPrivateIpAddress()); + final String cnct = citrixResourceBase.connect(conn, command.getVmName(), command.getPrivateIpAddress(), 0); citrixResourceBase.networkUsage(conn, command.getPrivateIpAddress(), "create", null); if (cnct == null) { diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java index ecd1b0d718c9..f4ee77c347f3 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java @@ -25,6 +25,7 @@ import java.util.Map; import java.util.Set; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; @@ -180,6 +181,29 @@ public Answer execute(final StartCommand command, final CitrixResourceBase citri state = VmPowerState.RUNNING; + String controlIp = null; + for (final NicTO nic : vmSpec.getNics()) { + if (nic.getType() == Networks.TrafficType.Control) { + controlIp = nic.getIp(); + break; + } + } + + String result2 = citrixResourceBase.connect(conn, vmName, controlIp, 1000); + if (StringUtils.isEmpty(result2)) { + s_logger.info(String.format("Connected to SystemVM: %s", vmName)); + } + + try { + citrixResourceBase.copyPatchFilesToVR(controlIp, "/home/cloud"); + // TODO: May want to remove this when cert patching logic is moved + Thread.sleep(10000); + } catch (Exception e) { + String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; + s_logger.error(errMsg, e); + return new StartAnswer(command, String.format("%s due to: %s", errMsg, e.getMessage())); + } + final StartAnswer startAnswer = new StartAnswer(command); startAnswer.setIqnToData(iqnToData); diff --git a/scripts/vm/hypervisor/xenserver/vmops b/scripts/vm/hypervisor/xenserver/vmops index dd03ded95927..e5c7e1a37880 100755 --- a/scripts/vm/hypervisor/xenserver/vmops +++ b/scripts/vm/hypervisor/xenserver/vmops @@ -235,11 +235,13 @@ def createFileInDomr(session, args): src_filepath = args['srcfilepath'] dst_path = args['dstfilepath'] domrip = args['domrip'] + cleanup = 'true' if 'cleanup' not in args else args['cleanup'] txt="" try: target = "root@" + domrip + ":" + dst_path txt = util.pread2(['scp','-P','3922','-q','-o','StrictHostKeyChecking=no','-i','/root/.ssh/id_rsa.cloud',src_filepath, target]) - util.pread2(['rm',src_filepath]) + if cleanup == 'true' or not cleanup: + util.pread2(['rm',src_filepath]) txt = 'succ#' + txt except: logging.debug("failed to copy file " + src_filepath + " from host to VR with ip " + domrip) diff --git a/scripts/vm/hypervisor/xenserver/xcposs/patch b/scripts/vm/hypervisor/xenserver/xcposs/patch index d3c5db052458..f855c660d3ce 100644 --- a/scripts/vm/hypervisor/xenserver/xcposs/patch +++ b/scripts/vm/hypervisor/xenserver/xcposs/patch @@ -32,6 +32,9 @@ ovsgre=..,0755,/usr/lib/xcp/plugins ovstunnel=..,0755,/usr/lib/xcp/plugins vmopsSnapshot=..,0755,/usr/lib/xcp/plugins systemvm.iso=../../../../../vms,0644,/usr/share/xcp/packages/iso/ +agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ +cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ +patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin setupxenserver.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xcpserver/patch b/scripts/vm/hypervisor/xenserver/xcpserver/patch index 32c7c46728d8..9768cba296da 100644 --- a/scripts/vm/hypervisor/xenserver/xcpserver/patch +++ b/scripts/vm/hypervisor/xenserver/xcpserver/patch @@ -32,8 +32,9 @@ vmops=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso -agent.zip=../../../../../vms,0644,/opt/xensource/packages/iso -cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/iso +agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ +cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ +patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin setupxenserver.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver56/patch b/scripts/vm/hypervisor/xenserver/xenserver56/patch index b6f7cdbb5c1b..8a784ae21e64 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver56/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver56/patch @@ -31,6 +31,9 @@ vmops=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ +cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ +patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin setupxenserver.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch b/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch index 4546796f9b36..93d2e4dee6ec 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch @@ -31,6 +31,9 @@ vmops=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ +cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ +patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin setupxenserver.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver60/patch b/scripts/vm/hypervisor/xenserver/xenserver60/patch index bea0cf9bfd17..0271d06f5cf4 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver60/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver60/patch @@ -35,6 +35,9 @@ cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ +cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ +patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin setupxenserver.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver62/patch b/scripts/vm/hypervisor/xenserver/xenserver62/patch index db137c9826f3..5fda3aff5514 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver62/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver62/patch @@ -36,6 +36,9 @@ cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins cloud-plugin-storage=..,0755,/etc/xapi.d/plugins systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ +cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ +patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin setupxenserver.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver65/patch b/scripts/vm/hypervisor/xenserver/xenserver65/patch index db137c9826f3..5fda3aff5514 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver65/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver65/patch @@ -36,6 +36,9 @@ cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins cloud-plugin-storage=..,0755,/etc/xapi.d/plugins systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ +cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ +patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin setupxenserver.sh=..,0755,/opt/cloud/bin diff --git a/tools/appliance/build.sh b/tools/appliance/build.sh index 79de31a9adeb..7075c135d42d 100755 --- a/tools/appliance/build.sh +++ b/tools/appliance/build.sh @@ -349,9 +349,9 @@ function main() { # process the disk at dist kvm_export -# ovm_export -# xen_server_export -# vmware_export + ovm_export + xen_server_export + vmware_export # hyperv_export rm -f "dist/${appliance}" cd dist && chmod +r * && cd .. diff --git a/utils/src/main/java/com/cloud/utils/FileUtil.java b/utils/src/main/java/com/cloud/utils/FileUtil.java index c55dd74e21bf..2121d3a7ae26 100644 --- a/utils/src/main/java/com/cloud/utils/FileUtil.java +++ b/utils/src/main/java/com/cloud/utils/FileUtil.java @@ -21,12 +21,35 @@ import java.io.File; import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.ssh.SshHelper; import org.apache.commons.io.FileUtils; +import org.apache.log4j.Logger; public class FileUtil { + private static final Logger s_logger = Logger.getLogger(FileUtil.class); public static void copyfile(File source, File destination) throws IOException { FileUtils.copyFile(source, destination); } + + public static void scpPatchFiles(String controlIp, String destPath, int sshPort, File pemFile, String[] files, String basePath) { + try { + List srcFiles = Arrays.asList(files); + srcFiles = srcFiles.stream() + .map(file -> basePath + file) // Using Lambda notation to update the entries + .collect(Collectors.toList()); + String[] newSrcFiles = srcFiles.toArray(new String[0]); + SshHelper.scpTo(controlIp, sshPort, "root", pemFile, null, + destPath, newSrcFiles, "0755"); + } catch (Exception e) { + String errMsg = "Failed to scp files to system VM"; + s_logger.error(errMsg, e); + throw new CloudRuntimeException(errMsg, e); + } + } } From 5cb090d40e805c147a0841a00e1cd81a4b380182 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Tue, 14 Dec 2021 18:25:07 +0530 Subject: [PATCH 03/68] - Support to patch SystemVMs - VMWare - Remove attaching systemvm.iso to systemVMs - Modify / Refactor VMware start command to copy patch related files to the systemvms - cleanup --- .../vmware/resource/VmwareResource.java | 114 +++++++++++++++++- .../CitrixPatchSystemVmCommandWrapper.java | 19 ++- scripts/vm/hypervisor/xenserver/vmops | 16 ++- .../java/com/cloud/vm/UserVmManagerImpl.java | 2 +- 4 files changed, 136 insertions(+), 15 deletions(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 297e5344a1dc..f258f6a6f8e5 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -47,6 +47,10 @@ import javax.naming.ConfigurationException; import javax.xml.datatype.XMLGregorianCalendar; +import com.cloud.agent.api.PatchSystemVmAnswer; +import com.cloud.agent.api.PatchSystemVmCommand; +import com.cloud.resource.ServerResourceBase; +import com.cloud.utils.FileUtil; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.storage.command.CopyCommand; import org.apache.cloudstack.storage.command.StorageSubSystemCommand; @@ -360,10 +364,11 @@ import com.vmware.vim25.VmwareDistributedVirtualSwitchPvlanSpec; import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanIdSpec; -public class VmwareResource implements StoragePoolResource, ServerResource, VmwareHostService, VirtualRouterDeployer { +public class VmwareResource extends ServerResourceBase implements StoragePoolResource, ServerResource, VmwareHostService, VirtualRouterDeployer { private static final Logger s_logger = Logger.getLogger(VmwareResource.class); public static final String VMDK_EXTENSION = ".vmdk"; private static final String EXECUTING_RESOURCE_COMMAND = "Executing resource command %s: [%s]."; + public static final String BASEPATH = "/usr/share/cloudstack-common/vms/"; private static final Random RANDOM = new Random(System.nanoTime()); @@ -590,7 +595,9 @@ public Answer executeRequest(Command cmd) { answer = execute((SetupPersistentNetworkCommand) cmd); } else if (clz == GetVmVncTicketCommand.class) { answer = execute((GetVmVncTicketCommand) cmd); - } else { + } else if (clz == PatchSystemVmCommand.class) { + answer = execute((PatchSystemVmCommand) cmd); + } else { answer = Answer.createUnsupportedCommandAnswer(cmd); } @@ -630,6 +637,68 @@ public Answer executeRequest(Command cmd) { return answer; } + private ExecutionResult getSystemVmVersionAndChecksum(String controlIp) { + ExecutionResult result; + try { + result = executeInVR(controlIp, VRScripts.VERSION, null); + if (!result.isSuccess()) { + String errMsg = String.format("GetSystemVMVersionCmd on %s failed, message %s", controlIp, result.getDetails()); + s_logger.error(errMsg); + throw new CloudRuntimeException(errMsg); + } + } catch (final Exception e) { + final String msg = "GetSystemVMVersionCmd failed due to " + e; + s_logger.error(msg, e); + throw new CloudRuntimeException(msg, e); + } + return result; + } + + private Answer execute(PatchSystemVmCommand cmd) { + String controlIp = getRouterSshControlIp(cmd); + String sysVMName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + String homeDir = System.getProperty("user.home"); + File pemFile = new File(homeDir + "/.ssh/id_rsa"); + + ExecutionResult result = getSystemVmVersionAndChecksum(controlIp); + try { + FileUtil.scpPatchFiles(controlIp, "/home/cloud", DefaultDomRSshPort, pemFile, newSrcFiles, BASEPATH); + } catch (CloudRuntimeException e) { + return new PatchSystemVmAnswer(cmd, e.getMessage()); + } + + final String[] lines = result.getDetails().split("&"); + // TODO: do we fail, or patch anyway?? + if (lines.length != 2) { + return new PatchSystemVmAnswer(cmd, result.getDetails()); + } + + String scriptChecksum = lines[1].trim(); + String checksum = calculateCurrentChecksum(sysVMName).trim(); + + if (!org.apache.commons.lang3.StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum)) { + if (!cmd.isForced()) { + String msg = String.format("No change in the scripts checksum, not patching systemVM %s", sysVMName); + s_logger.info(msg); + return new PatchSystemVmAnswer(cmd, msg, lines[0], lines[1]); + } + } + + Pair patchResult = null; + try { + patchResult = SshHelper.sshExecute(controlIp, DefaultDomRSshPort, "root", + pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 60000); + } catch (Exception e) { + return new PatchSystemVmAnswer(cmd, e.getMessage()); + } + + if (patchResult.first()) { + return new PatchSystemVmAnswer(cmd, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], lines[1]); + } + return new PatchSystemVmAnswer(cmd, patchResult.second()); + + } + private Answer execute(SetupPersistentNetworkCommand cmd) { VmwareHypervisorHost host = getHyperHost(getServiceContext()); String hostname = null; @@ -2072,7 +2141,7 @@ protected StartAnswer execute(StartCommand cmd) { deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec(); Pair isoInfo = VmwareHelper.prepareIsoDevice(vmMo, - String.format("[%s] systemvm/%s", secDsMo.getName(), mgr.getSystemVMIsoFileNameOnDatastore()), secDsMo.getMor(), true, true, ideUnitNumber++, i + 1); + null, secDsMo.getMor(), true, true, ideUnitNumber++, i + 1); deviceConfigSpecArray[i].setDevice(isoInfo.first()); if (isoInfo.second()) { if (s_logger.isDebugEnabled()) @@ -2457,6 +2526,29 @@ protected StartAnswer execute(StartCommand cmd) { startAnswer.setIqnToData(iqnToData); + if (vmSpec.getType() != VirtualMachine.Type.User) { + String controlIp = getControlIp(nics); + // check if the router is up? + for (int count = 0; count < 60; count++) { + final boolean result = _vrResource.connect(controlIp, 1, 5000); + if (result) { + break; + } + } + + try { + String homeDir = System.getProperty("user.home"); + File pemFile = new File(homeDir + "/.ssh/id_rsa"); + FileUtil.scpPatchFiles(controlIp, "/home/cloud", DefaultDomRSshPort, pemFile, newSrcFiles, BASEPATH); + // TODO: May want to remove this when cert patching logic is moved + Thread.sleep(10000); + } catch (Exception e) { + String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; + s_logger.error(errMsg, e); + return new StartAnswer(cmd, String.format("%s due to: %s", errMsg, e.getMessage())); + } + } + // Since VM was successfully powered-on, if there was an existing VM in a different cluster that was unregistered, delete all the files associated with it. if (existingVmName != null && existingVmFileLayout != null) { List vmDatastoreNames = new ArrayList(); @@ -3848,6 +3940,17 @@ private String getNetworkNamePrefix(NicTO nicTo) throws Exception { } } + private String getControlIp(NicTO[] nicTOs) { + String controlIpAddress = null; + for (NicTO nic : nicTOs) { + if ((TrafficType.Management == nic.getType() || TrafficType.Control == nic.getType()) && nic.getIp() != null) { + controlIpAddress = nic.getIp(); + break; + } + } + return controlIpAddress; + } + private VirtualMachineMO takeVmFromOtherHyperHost(VmwareHypervisorHost hyperHost, String vmName) throws Exception { VirtualMachineMO vmMo = hyperHost.findVmOnPeerHyperHost(vmName); @@ -6650,6 +6753,11 @@ public String getName() { return _name; } + @Override + protected String getDefaultScriptsDir() { + return null; + } + @Override public boolean start() { return true; diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java index e27381e694da..a6b183f9d11e 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java @@ -25,10 +25,8 @@ import com.cloud.resource.CommandWrapper; import com.cloud.resource.ResourceWrapper; import com.cloud.utils.ExecutionResult; -import com.cloud.utils.FileUtil; -import com.cloud.utils.Pair; import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.ssh.SshHelper; +import com.xensource.xenapi.Connection; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; @@ -44,12 +42,13 @@ public class CitrixPatchSystemVmCommandWrapper extends CommandWrapper patchResult = null; + String patchResult = null; try { - patchResult = SshHelper.sshExecute(controlIp, sshPort, "root", - pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 60000); + patchResult = serverResource.callHostPlugin(conn, "vmops", "runPatchScriptInDomr", "domrip", controlIp); } catch (Exception e) { return new PatchSystemVmAnswer(command, e.getMessage()); } - if (patchResult.first()) { + + if (patchResult.startsWith("succ#")) { return new PatchSystemVmAnswer(command, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], lines[1]); } - return new PatchSystemVmAnswer(command, patchResult.second()); + return new PatchSystemVmAnswer(command, patchResult.substring(5)); } diff --git a/scripts/vm/hypervisor/xenserver/vmops b/scripts/vm/hypervisor/xenserver/vmops index e5c7e1a37880..cea47cce2975 100755 --- a/scripts/vm/hypervisor/xenserver/vmops +++ b/scripts/vm/hypervisor/xenserver/vmops @@ -248,6 +248,19 @@ def createFileInDomr(session, args): txt = 'fail#' + txt return txt +@echo +def runPatchScriptInDomr(session, args): + domrip = args['domrip'] + txt="" + try: + target = "root@" + domrip + txt = util.pread2(['ssh','-p','3922','-i','/root/.ssh/id_rsa.cloud', target, "/bin/bash","/home/cloud/patch-sysvms.sh"]) + txt = 'succ#' + txt + except: + logging.debug("failed to run patch script in systemVM with IP: " + domrip) + txt = 'fail#' + txt + return txt + @echo def deleteFile(session, args): file_path = args["filepath"] @@ -1590,4 +1603,5 @@ if __name__ == "__main__": "cleanup_rules":cleanup_rules, "createFileInDomr":createFileInDomr, "kill_copy_process":kill_copy_process, - "secureCopyToHost":secureCopyToHost}) + "secureCopyToHost":secureCopyToHost, + "runPatchScriptInDomr": runPatchScriptInDomr}) diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index 275f7018b40e..581995d07fcf 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -4896,7 +4896,7 @@ public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile prof } @Override - public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { + public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { UserVmVO vm = _vmDao.findById(profile.getId()); Answer[] answersToCmds = cmds.getAnswers(); From 86bc3bf1def26c55b1a75ec51cb044492ce8092e Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Tue, 21 Dec 2021 14:24:32 +0530 Subject: [PATCH 04/68] Commit comprises of: - remove docker from systemvm template - use containerd as container runtime - update create-k8s-binaries script to use ctr for all docker operations - Update userdata sent to the k8s nodes - update cksnode script, run during patching of the cks/k8s nodes --- .../resource/LibvirtComputingResource.java | 26 ++++------------- .../resources/conf/k8s-control-node-add.yml | 10 +++---- .../main/resources/conf/k8s-control-node.yml | 12 ++++---- .../src/main/resources/conf/k8s-node.yml | 10 +++---- .../resources/script/upgrade-kubernetes.sh | 2 +- .../util/create-kubernetes-binaries-iso.sh | 22 +++++++------- .../consoleproxy/ConsoleProxyManagerImpl.java | 8 +++++ .../debian/opt/cloud/bin/setup/cksnode.sh | 9 ++++-- .../opt/cloud/bin/setup/cloud-early-config | 29 +++++++++++++------ systemvm/debian/opt/cloud/bin/setup/common.sh | 6 ++++ systemvm/patch-sysvms.sh | 3 +- .../scripts/configure_systemvm_services.sh | 4 --- .../scripts/install_systemvm_packages.sh | 2 +- 13 files changed, 77 insertions(+), 66 deletions(-) diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index e7cdfbb925f7..99296e2e40fd 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -1168,20 +1168,6 @@ public boolean configure(final String name, final Map params) th _storagePoolMgr = new KVMStoragePoolManager(_storage, _monitor); - _sysvmISOPath = (String)params.get("systemvm.iso.path"); - if (_sysvmISOPath == null) { - final String[] isoPaths = {"/usr/share/cloudstack-common/vms/systemvm.iso"}; - for (final String isoPath : isoPaths) { - if (_storage.exists(isoPath)) { - _sysvmISOPath = isoPath; - break; - } - } - if (_sysvmISOPath == null) { - s_logger.debug("Can't find system vm ISO"); - } - } - final Map bridges = new HashMap(); params.put("libvirt.host.bridges", bridges); @@ -2902,14 +2888,12 @@ public int compare(final DiskTO arg0, final DiskTO arg1) { } if (vmSpec.getType() != VirtualMachine.Type.User) { - if (_sysvmISOPath != null) { - final DiskDef iso = new DiskDef(); - // iso.defISODisk(_sysvmISOPath); - if (_guestCpuArch != null && _guestCpuArch.equals("aarch64")) { - iso.setBusType(DiskDef.DiskBus.SCSI); - } - vm.getDevices().addDevice(iso); + final DiskDef iso = new DiskDef(); + iso.defISODisk(_sysvmISOPath); + if (_guestCpuArch != null && _guestCpuArch.equals("aarch64")) { + iso.setBusType(DiskDef.DiskBus.SCSI); } + vm.getDevices().addDevice(iso); } // For LXC, find and add the root filesystem, rbd data disks diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml index 0891d2015b30..87c592426a96 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml @@ -118,7 +118,7 @@ write_files: fi retval=0 set +e - docker load < "${BINARIES_DIR}/docker/$line" + ctr image import "${BINARIES_DIR}/docker/$line" retval=$? set -e if [ $retval -eq 0 ]; then @@ -165,7 +165,7 @@ write_files: fi systemctl enable kubelet && systemctl start kubelet - modprobe br_netfilter && sysctl net.bridge.bridge-nf-call-iptables=1 + modprobe overlay && modprobe br_netfilter && sysctl net.bridge.bridge-nf-call-iptables=1 if [ -d "$BINARIES_DIR" ] && [ "$ATTEMPT_ONLINE_INSTALL" = true ]; then crucial_cmd_attempts=1 @@ -176,7 +176,7 @@ write_files: fi retval=0 set +e - kubeadm config images pull + kubeadm config images pull --cri-socket /run/containerd/containerd.sock retval=$? set -e if [ $retval -eq 0 ]; then @@ -218,8 +218,8 @@ write_files: owner: root:root content: | [Unit] - Requires=docker.service - After=docker.service + Requires=containerd.service + After=containerd.service [Service] Type=simple diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml index 322f08099cf7..55daf7f6b7d3 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml @@ -138,7 +138,7 @@ write_files: fi retval=0 set +e - docker load < "${BINARIES_DIR}/docker/$line" + ctr image import "${BINARIES_DIR}/docker/$line" retval=$? set -e if [ $retval -eq 0 ]; then @@ -187,7 +187,7 @@ write_files: fi systemctl enable kubelet && systemctl start kubelet - modprobe br_netfilter && sysctl net.bridge.bridge-nf-call-iptables=1 + modprobe overlay && modprobe br_netfilter && sysctl net.bridge.bridge-nf-call-iptables=1 if [ -d "$BINARIES_DIR" ] && [ "$ATTEMPT_ONLINE_INSTALL" = true ]; then crucial_cmd_attempts=1 @@ -198,7 +198,7 @@ write_files: fi retval=0 set +e - kubeadm config images pull + kubeadm config images pull --cri-socket /run/containerd/containerd.sock retval=$? set -e if [ $retval -eq 0 ]; then @@ -216,7 +216,7 @@ write_files: fi retval=0 set +e - kubeadm init --token {{ k8s_control_node.cluster.token }} --token-ttl 0 {{ k8s_control_node.cluster.initargs }} + kubeadm init --token {{ k8s_control_node.cluster.token }} --token-ttl 0 {{ k8s_control_node.cluster.initargs }} --cri-socket /run/containerd/containerd.sock retval=$? set -e if [ $retval -eq 0 ]; then @@ -275,8 +275,8 @@ write_files: owner: root:root content: | [Unit] - Requires=docker.service - After=docker.service + Requires=containerd.service + After=containerd.service [Service] Type=simple diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml index 28ba43e75845..ac05c6098f1a 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml @@ -118,7 +118,7 @@ write_files: fi retval=0 set +e - docker load < "${BINARIES_DIR}/docker/$line" + ctr image import "${BINARIES_DIR}/docker/$line" retval=$? set -e if [ $retval -eq 0 ]; then @@ -165,7 +165,7 @@ write_files: fi systemctl enable kubelet && systemctl start kubelet - modprobe br_netfilter && sysctl net.bridge.bridge-nf-call-iptables=1 + modprobe overlay && modprobe br_netfilter && sysctl net.bridge.bridge-nf-call-iptables=1 if [ -d "$BINARIES_DIR" ] && [ "$ATTEMPT_ONLINE_INSTALL" = true ]; then crucial_cmd_attempts=1 @@ -176,7 +176,7 @@ write_files: fi retval=0 set +e - kubeadm config images pull + kubeadm config images pull --cri-socket /run/containerd/containerd.sock retval=$? set -e if [ $retval -eq 0 ]; then @@ -218,8 +218,8 @@ write_files: owner: root:root content: | [Unit] - Requires=docker.service - After=docker.service + Requires=containerd.service + After=containerd.service [Service] Type=simple diff --git a/plugins/integrations/kubernetes-service/src/main/resources/script/upgrade-kubernetes.sh b/plugins/integrations/kubernetes-service/src/main/resources/script/upgrade-kubernetes.sh index 7e0c3c00a8a5..b85ea00e9ed6 100755 --- a/plugins/integrations/kubernetes-service/src/main/resources/script/upgrade-kubernetes.sh +++ b/plugins/integrations/kubernetes-service/src/main/resources/script/upgrade-kubernetes.sh @@ -93,7 +93,7 @@ if [ -d "$BINARIES_DIR" ]; then output=`ls ${BINARIES_DIR}/docker/` if [ "$output" != "" ]; then while read -r line; do - docker load < "${BINARIES_DIR}/docker/$line" + ctr image import "${BINARIES_DIR}/docker/$line" done <<< "$output" fi if [ -e "${BINARIES_DIR}/provider.yaml" ]; then diff --git a/scripts/util/create-kubernetes-binaries-iso.sh b/scripts/util/create-kubernetes-binaries-iso.sh index ba3dca77a8d2..ce7626c98c22 100755 --- a/scripts/util/create-kubernetes-binaries-iso.sh +++ b/scripts/util/create-kubernetes-binaries-iso.sh @@ -98,19 +98,18 @@ provider_conf_file="${working_dir}/provider.yaml" curl -sSL ${PROVIDER_URL} -o ${provider_conf_file} echo "Fetching k8s docker images..." -docker -v +ctr -v if [ $? -ne 0 ]; then - echo "Installing docker..." + echo "Installing containerd..." if [ -f /etc/redhat-release ]; then sudo yum -y remove docker-common docker container-selinux docker-selinux docker-engine sudo yum -y install lvm2 device-mapper device-mapper-persistent-data device-mapper-event device-mapper-libs device-mapper-event-libs sudo yum install -y http://mirror.centos.org/centos/7/extras/x86_64/Packages/container-selinux-2.107-3.el7.noarch.rpm - sudo wget https://download.docker.com/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo && sudo yum -y install docker-ce - sudo systemctl enable docker && sudo systemctl start docker + sudo yum install -y containerd.io elif [ -f /etc/lsb-release ]; then - sudo apt update && sudo apt install docker.io -y - sudo systemctl enable docker && sudo systemctl start docker + sudo apt update && sudo apt install containerd.io -y fi + sudo systemctl enable containerd && sudo systemctl start containerd fi mkdir -p "${working_dir}/docker" output=`${k8s_dir}/kubeadm config images list --kubernetes-version=${RELEASE}` @@ -130,11 +129,14 @@ provider_image=`grep "image:" ${provider_conf_file} | cut -d ':' -f2- | tr -d ' output=`printf "%s\n" ${output} ${provider_image}` while read -r line; do - echo "Downloading docker image $line ---" - sudo docker pull "$line" + echo "Downloading image $line ---" + if [[ $line == kubernetesui* ]] || [[ $line == apache* ]]; then + line="docker.io/${line}" + fi + sudo ctr image pull "$line" image_name=`echo "$line" | grep -oE "[^/]+$"` - sudo docker save "$line" > "${working_dir}/docker/$image_name.tar" - sudo docker image rm "$line" + sudo ctr image export "${working_dir}/docker/$image_name.tar" "$line" + sudo ctr image rm "$line" done <<< "$output" echo "Restore kubeadm permissions..." diff --git a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index a3177fa77054..7434ea89669c 100644 --- a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -29,7 +29,9 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.utils.PasswordGenerator; import org.apache.cloudstack.agent.lb.IndirectAgentLB; +import org.apache.cloudstack.ca.CAManager; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.framework.config.ConfigKey; @@ -221,6 +223,10 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy private VirtualMachineManager virtualMachineManager; @Inject private IndirectAgentLB indirectAgentLB; + @Inject + private CAManager caManager; + @Inject + private NetworkOrchestrationService networkMgr; private ConsoleProxyListener consoleProxyListener; @@ -1274,6 +1280,8 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl buf.append(" dns2=").append(dc.getDns2()); } + buf.append(" keystore_password=").append(PasswordGenerator.generateRandomPassword(16)); + buf.append(" validity=").append(CAManager.CertValidityPeriod.value()); String bootArgs = buf.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug("Boot Args for " + profile + ": " + bootArgs); diff --git a/systemvm/debian/opt/cloud/bin/setup/cksnode.sh b/systemvm/debian/opt/cloud/bin/setup/cksnode.sh index 612fdd477e8f..7f580ace9cd4 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cksnode.sh +++ b/systemvm/debian/opt/cloud/bin/setup/cksnode.sh @@ -28,18 +28,23 @@ setup_k8s_node() { # set default ssh port and restart sshd service sed -i 's/3922/22/g' /etc/ssh/sshd_config + systemctl restart ssh # Prevent root login > /root/.ssh/authorized_keys passwd -l root #sed -i 's#root:x:0:0:root:/root:/bin/bash#root:x:0:0:root:/root:/sbin/nologin#' /etc/passwd + # Update containerd configuration + mkdir -p /etc/containerd + containerd config default>/etc/containerd/config.toml + systemctl restart containerd + swapoff -a sudo sed -i '/ swap / s/^/#/' /etc/fstab log_it "Swap disabled" log_it "Setting up interfaces" -# setup_common eth0 setup_system_rfc1918_internal log_it "Setting up entry in hosts" @@ -61,8 +66,6 @@ setup_k8s_node() { log_it "Starting cloud-init services" systemctl enable --now --no-block containerd - systemctl enable --now --no-block docker.socket - systemctl enable --now --no-block docker.service if [ -f /home/core/success ]; then systemctl stop cloud-init cloud-config cloud-final systemctl disable cloud-init cloud-config cloud-final diff --git a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config index 9695b18307bb..370dfc0c6205 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config +++ b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config @@ -31,29 +31,40 @@ log_it() { log_action_msg "$@" } +validate_checksums() { + local oldmd5= + [ -f ${1} ] && oldmd5=$(cat ${1}) + local newmd5= + [ -f ${2} ] && newmd5=$(md5sum ${2} | awk '{print $1}') + log_it "Scripts checksum detected: oldmd5=$oldmd5 newmd5=$newmd5" >> /dev/null 2>&1 + echo "oldmd5='${oldmd5}'; newmd5='${newmd5}'" +} + patch() { local PATCH_MOUNT=/home/cloud - local patchfile=$PATCH_MOUNT/cloud-scripts.tgz + local PATCH_SCRIPTS=cloud-scripts.tgz + local oldpatchfile=/usr/share/cloud/$PATCH_SCRIPTS + local patchfile=$PATCH_MOUNT/$PATCH_SCRIPTS local privkey=$PATCH_MOUNT/authorized_keys local md5file=/var/cache/cloud/cloud-scripts-signature - local cdrom_dev= mkdir -p $PATCH_MOUNT if [ -f /var/cache/cloud/authorized_keys ]; then privkey=/var/cache/cloud/authorized_keys fi + eval $(validate_checksums $md5file $oldpatchfile) + if [ "$oldmd5" == "$newmd5" ] && [ ! -f ${patchfile} ]; then + log_it "Checksum matches, do need to patch" + return 0 + fi + retry=60 local patched=false while [ $retry -gt 0 ] do if [ -f $patchfile ]; then - local oldmd5= - [ -f ${md5file} ] && oldmd5=$(cat ${md5file}) - local newmd5= - [ -f ${patchfile} ] && newmd5=$(md5sum ${patchfile} | awk '{print $1}') - log_it "Scripts checksum detected: oldmd5=$oldmd5 newmd5=$newmd5" - log_it ls -lrt $PATCH_MOUNT + eval $(validate_checksums $md5file $patchfile) if [ "$oldmd5" != "$newmd5" ] && [ -f ${patchfile} ] && [ "$newmd5" != "" ] then tar xzf $patchfile -C / @@ -84,7 +95,7 @@ patch() { cleanup() { rm -rf /home/cloud/agent.zip - rm -rf /home/cloud/cloud-scripts.tgz + mv /home/cloud/cloud-scripts.tgz /usr/share/cloud/cloud-scripts.tgz } start() { diff --git a/systemvm/debian/opt/cloud/bin/setup/common.sh b/systemvm/debian/opt/cloud/bin/setup/common.sh index 7f3d85717791..75c8f3cee755 100755 --- a/systemvm/debian/opt/cloud/bin/setup/common.sh +++ b/systemvm/debian/opt/cloud/bin/setup/common.sh @@ -762,6 +762,12 @@ parse_cmd_line() { authorized_key) export AUTHORIZED_KEYS=$VALUE ;; + keystore_password) + export KEYSTORE_PSSWD=$VALUE + ;; + validity) + export VALIDITY=$VALUE + ;; esac done echo -e "\n\t}\n}" >> ${CHEF_TMP_FILE} diff --git a/systemvm/patch-sysvms.sh b/systemvm/patch-sysvms.sh index cf0b452f82ed..31478d7269ae 100644 --- a/systemvm/patch-sysvms.sh +++ b/systemvm/patch-sysvms.sh @@ -76,7 +76,8 @@ restart_services() { cleanup_systemVM() { rm -rf $backupfolder - rm -rf "$newpath""cloud-scripts.tgz" "$newpath""agent.zip" "$newpath""patch-sysvms.sh" + mv "$newpath"cloud-scripts.tgz /usr/share/cloud/cloud-scripts.tgz + rm -rf "$newpath""agent.zip" "$newpath""patch-sysvms.sh" } patch_systemvm() { diff --git a/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh b/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh index 8cdfce787534..4f97b1b5505e 100644 --- a/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh +++ b/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh @@ -127,10 +127,6 @@ function configure_services() { # Disable container services systemctl disable containerd - systemctl disable docker.service - systemctl stop docker.service - systemctl disable docker.socket - systemctl stop docker.socket # Disable cloud init by default cat < /etc/cloud/cloud.cfg.d/cloudstack.cfg diff --git a/tools/appliance/systemvmtemplate/scripts/install_systemvm_packages.sh b/tools/appliance/systemvmtemplate/scripts/install_systemvm_packages.sh index 555a00c28edb..3b4ef6537286 100644 --- a/tools/appliance/systemvmtemplate/scripts/install_systemvm_packages.sh +++ b/tools/appliance/systemvmtemplate/scripts/install_systemvm_packages.sh @@ -98,7 +98,7 @@ function install_packages() { apt-key fingerprint 0EBFCD88 add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" apt-get update - ${apt_get} install docker-ce docker-ce-cli containerd.io + ${apt_get} install containerd.io apt_clean From 5a27cb70b17e2abbf512e02f763af97b3e70c647 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Tue, 21 Dec 2021 14:55:25 +0530 Subject: [PATCH 05/68] Add ssh to k8s nodes details in the Access tab on the UI --- ui/public/locales/en.json | 2 ++ ui/src/views/compute/KubernetesServiceTab.vue | 3 +++ 2 files changed, 5 insertions(+) diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index bd4bdf80f9e3..d81dd7a1e3ec 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -46,6 +46,7 @@ "label.accept": "Accept", "label.accept.project.invitation": "Accept project invitation", "label.access": "Access", +"label.acess.kubernetes.nodes": "Access Kubernetes Nodes", "label.accesskey": "Access Key", "label.account": "Account", "label.account.and.security.group": "Account - Security group", @@ -1240,6 +1241,7 @@ "label.keypair": "SSH Key Pair", "label.kubeconfig.cluster": "Kubernetes Cluster Config", "label.kubernetes": "Kubernetes", +"label.kubernetes.access.details": "The kubernetes nodes can be accessed via ssh using:
ssh -i [ssh_key] -p [port_number] core@[public_ip_address]

where,
ssh_key: points to the ssh private key file corresponding to the key that was associated while creating the Kubernetes cluster. If no ssh key was provided during Kubernetes cluster creation, use the ssh private key of the management server.
port_number: can be obtained from the Port Forwarding Tab (Public Port column)", "label.kubernetes.cluster": "Kubernetes cluster", "label.kubernetes.cluster.create": "Create Kubernetes Cluster", "label.kubernetes.cluster.delete": "Delete Kubernetes Cluster", diff --git a/ui/src/views/compute/KubernetesServiceTab.vue b/ui/src/views/compute/KubernetesServiceTab.vue index 4cf5486d33f6..9357a2473c5c 100644 --- a/ui/src/views/compute/KubernetesServiceTab.vue +++ b/ui/src/views/compute/KubernetesServiceTab.vue @@ -88,6 +88,9 @@

{{ $t('label.more.access.dashboard.ui') }}, https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/#accessing-the-dashboard-ui

+ +

+
Date: Wed, 22 Dec 2021 14:14:36 +0530 Subject: [PATCH 06/68] test --- .../com/cloud/vm/VirtualMachineManagerImpl.java | 3 +++ engine/schema/pom.xml | 14 ++++++++++---- pom.xml | 2 +- .../consoleproxy/ConsoleProxyManagerImpl.java | 12 +++++++++++- .../debian/opt/cloud/bin/setup/cloud-early-config | 2 +- tools/appliance/build.sh | 6 +++--- 6 files changed, 29 insertions(+), 10 deletions(-) diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index 2cbcf6fb9d1f..74eccf7865cd 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -992,6 +992,9 @@ private void setupAgentSecurity(final Host vmHost, final Map ssh final String csr = caManager.generateKeyStoreAndCsr(vmHost, sshAccessDetails); if (org.apache.commons.lang3.StringUtils.isNotEmpty(csr)) { final Map ipAddressDetails = new HashMap<>(sshAccessDetails); + for (Map.Entry e : ipAddressDetails.entrySet()) { + s_logger.info("PEARL - k = " + e.getKey() + " v: "+ e.getValue()); + } ipAddressDetails.remove(NetworkElementCommand.ROUTER_NAME); final Certificate certificate = caManager.issueCertificate(csr, Arrays.asList(vm.getHostName(), vm.getInstanceName()), new ArrayList<>(ipAddressDetails.values()), CAManager.CertValidityPeriod.value(), null); diff --git a/engine/schema/pom.xml b/engine/schema/pom.xml index adee9110007b..165887e19aea 100644 --- a/engine/schema/pom.xml +++ b/engine/schema/pom.xml @@ -90,7 +90,9 @@ def csVersion = pom.properties['cs.version'] + println(csVersion) def patch = pom.properties['patch.version'] + println(patch) def templateList = [] templateList.add("systemvmtemplate-${csVersion}.${patch}-kvm") templateList.add("systemvmtemplate-${csVersion}.${patch}-vmware") @@ -123,7 +125,8 @@ wget - https://download.cloudstack.org/systemvm/${cs.version}/md5sum.txt + + http://10.0.3.122/systemvmtemplate/custom/cks-debian/${cs.version}/md5sum.txt ${basedir}/dist/systemvm-templates/ true true @@ -182,7 +185,8 @@ true - https://download.cloudstack.org/systemvm/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-kvm.qcow2.bz2 + + http://10.0.3.122/systemvmtemplate/custom/cks-debian/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-kvm.qcow2.bz2 ${basedir}/dist/systemvm-templates/ ${kvm.checksum} @@ -194,7 +198,8 @@ true - https://download.cloudstack.org/systemvm/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-vmware.ova + + http://10.0.3.122/systemvmtemplate/custom/cks-debian/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-vmware.ova ${basedir}/dist/systemvm-templates/ ${vmware.checksum} @@ -206,7 +211,8 @@ true - https://download.cloudstack.org/systemvm/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-xen.vhd.bz2 + + http://10.0.3.122/systemvmtemplate/custom/cks-debian/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-xen.vhd.bz2 ${basedir}/dist/systemvm-templates/ ${xen.checksum} diff --git a/pom.xml b/pom.xml index 718430eb867e..4daaa8ccfca5 100644 --- a/pom.xml +++ b/pom.xml @@ -49,7 +49,7 @@ UTF-8 UTF-8 - 4.16.0.0 + 4.16.1.0 11 diff --git a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 7434ea89669c..1dcaf7b0b33e 100644 --- a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -1210,7 +1210,8 @@ protected ConsoleProxyManagerImpl() { @Override public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { - +// final Certificate certificate = caManager.issueCertificate(null, Arrays.asList(profile.getHostName(), profile.getInstanceName()), +// new ArrayList<>(ipAddressDetails.values()), CAManager.CertValidityPeriod.value(), null); ConsoleProxyVO vm = consoleProxyDao.findById(profile.getId()); Map details = userVmDetailsDao.listDetailsKeyPairs(vm.getId()); vm.setDetails(details); @@ -1280,6 +1281,15 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl buf.append(" dns2=").append(dc.getDns2()); } +// try { +// buf.append(" certificate=").append(CertUtils.x509CertificateToPem(certificate.getClientCertificate())); +// buf.append(" cacertificate=").append(CertUtils.x509CertificatesToPem(certificate.getCaCertificates())); +// if (certificate.getPrivateKey() != null) { +// buf.append(" privatekey=").append(CertUtils.privateKeyToPem(certificate.getPrivateKey())); +// } +// } catch (IOException e) { +// throw new CloudRuntimeException("Failed to transform X509 cert to PEM format", e); +// } buf.append(" keystore_password=").append(PasswordGenerator.generateRandomPassword(16)); buf.append(" validity=").append(CAManager.CertValidityPeriod.value()); String bootArgs = buf.toString(); diff --git a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config index 370dfc0c6205..5a50fe850079 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config +++ b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config @@ -54,7 +54,7 @@ patch() { fi eval $(validate_checksums $md5file $oldpatchfile) - if [ "$oldmd5" == "$newmd5" ] && [ ! -f ${patchfile} ]; then + if [ "$oldmd5" == "$newmd5" ] && [ -d /usr/local/cloud/systemvm ] && [ "$(ls -A /usr/local/cloud/systemvm)" ]; then log_it "Checksum matches, do need to patch" return 0 fi diff --git a/tools/appliance/build.sh b/tools/appliance/build.sh index 7075c135d42d..285d818c0c75 100755 --- a/tools/appliance/build.sh +++ b/tools/appliance/build.sh @@ -348,9 +348,9 @@ function main() { packer_build # process the disk at dist - kvm_export - ovm_export - xen_server_export +# kvm_export +# ovm_export +# xen_server_export vmware_export # hyperv_export rm -f "dist/${appliance}" From 8f1e3a340fa2ef8d0af4afe8e748eca38135a8c6 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Fri, 24 Dec 2021 12:20:41 +0530 Subject: [PATCH 07/68] Refactor ca/cert patching logic --- .../java/com/cloud/vm/VirtualMachineGuru.java | 25 +++++++++++ .../cloud/vm/VirtualMachineManagerImpl.java | 17 ------- scripts/util/keystore-cert-import | 45 ++++++++++++------- .../consoleproxy/ConsoleProxyManagerImpl.java | 21 +++------ .../com/cloud/consoleproxy/ConsoleProxy.java | 10 ++++- .../SecondaryStorageManagerImpl.java | 11 +++++ .../opt/cloud/bin/setup/cloud-early-config | 2 +- systemvm/debian/opt/cloud/bin/setup/common.sh | 22 ++++++++- .../opt/cloud/bin/setup/consoleproxy.sh | 2 + .../debian/opt/cloud/bin/setup/secstorage.sh | 1 + 10 files changed, 104 insertions(+), 52 deletions(-) diff --git a/engine/api/src/main/java/com/cloud/vm/VirtualMachineGuru.java b/engine/api/src/main/java/com/cloud/vm/VirtualMachineGuru.java index 7611df820c80..d6d7513fd5c6 100644 --- a/engine/api/src/main/java/com/cloud/vm/VirtualMachineGuru.java +++ b/engine/api/src/main/java/com/cloud/vm/VirtualMachineGuru.java @@ -20,7 +20,14 @@ import com.cloud.agent.manager.Commands; import com.cloud.deploy.DeployDestination; import com.cloud.exception.ResourceUnavailableException; +import com.cloud.utils.PasswordGenerator; +import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.cloudstack.ca.CAManager; +import org.apache.cloudstack.framework.ca.Certificate; +import org.apache.cloudstack.utils.security.CertUtils; +import org.apache.cloudstack.utils.security.KeyStoreUtils; +import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Base64; @@ -72,4 +79,22 @@ static String getEncodedMsPublicKey(String pubKey) { } return base64EncodedPublicKey; } + + private static String getEncodedString(String certificate) { + return Base64.getEncoder().encodeToString(certificate.replace("\n", KeyStoreUtils.CERT_NEWLINE_ENCODER).replace(" ", KeyStoreUtils.CERT_SPACE_ENCODER).getBytes(StandardCharsets.UTF_8)); + } + + static void appendCertificateDetails(StringBuilder buf, Certificate certificate) { + try { + buf.append(" certificate=").append(getEncodedString(CertUtils.x509CertificateToPem(certificate.getClientCertificate()))); + buf.append(" cacertificate=").append(getEncodedString(CertUtils.x509CertificatesToPem(certificate.getCaCertificates()))); + if (certificate.getPrivateKey() != null) { + buf.append(" privatekey=").append(getEncodedString(CertUtils.privateKeyToPem(certificate.getPrivateKey()))); + } + } catch (IOException e) { + throw new CloudRuntimeException("Failed to transform X509 cert to PEM format", e); + } + buf.append(" keystore_password=").append(getEncodedString(PasswordGenerator.generateRandomPassword(16))); + buf.append(" validity=").append(CAManager.CertValidityPeriod.value()); + } } diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index 74eccf7865cd..fdd77d6c23fb 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -992,9 +992,6 @@ private void setupAgentSecurity(final Host vmHost, final Map ssh final String csr = caManager.generateKeyStoreAndCsr(vmHost, sshAccessDetails); if (org.apache.commons.lang3.StringUtils.isNotEmpty(csr)) { final Map ipAddressDetails = new HashMap<>(sshAccessDetails); - for (Map.Entry e : ipAddressDetails.entrySet()) { - s_logger.info("PEARL - k = " + e.getKey() + " v: "+ e.getValue()); - } ipAddressDetails.remove(NetworkElementCommand.ROUTER_NAME); final Certificate certificate = caManager.issueCertificate(csr, Arrays.asList(vm.getHostName(), vm.getInstanceName()), new ArrayList<>(ipAddressDetails.values()), CAManager.CertValidityPeriod.value(), null); @@ -1246,20 +1243,6 @@ public void orchestrateStart(final String vmUuid, final Map sshAccessDetails = _networkMgr.getSystemVMAccessDetails(vm); - for (int retries = 3; retries > 0; retries--) { - try { - setupAgentSecurity(vmHost, sshAccessDetails, vm); - return; - } catch (final AgentUnavailableException | OperationTimedoutException e) { - s_logger.error("Retrying after catching exception while trying to secure agent for systemvm id=" + vm.getId(), e); - } - } - throw new CloudRuntimeException("Failed to setup and secure agent for systemvm id=" + vm.getId()); - } return; } else { if (s_logger.isDebugEnabled()) { diff --git a/scripts/util/keystore-cert-import b/scripts/util/keystore-cert-import index a2b57bff07e2..8e63e9509cc0 100755 --- a/scripts/util/keystore-cert-import +++ b/scripts/util/keystore-cert-import @@ -17,19 +17,39 @@ # under the License. PROPS_FILE="$1" -KS_FILE="$2" -MODE="$3" -CERT_FILE="$4" -CERT=$(echo "$5" | tr '^' '\n' | tr '~' ' ') -CACERT_FILE="$6" -CACERT=$(echo "$7" | tr '^' '\n' | tr '~' ' ') -PRIVKEY_FILE="$8" -PRIVKEY=$(echo "$9" | tr '^' '\n' | tr '~' ' ') +KS_PASS="$2" +KS_VALIDITY="$3" +KS_FILE="$4" +MODE="$5" +CERT_FILE="$6" +CERT=$(echo "$7" | tr '^' '\n' | tr '~' ' ') +CACERT_FILE="$8" +CACERT=$(echo "$9" | tr '^' '\n' | tr '~' ' ') +PRIVKEY_FILE="${10}" +PRIVKEY=$(echo "${11}" | tr '^' '\n' | tr '~' ' ') ALIAS="cloud" SYSTEM_FILE="/var/cache/cloud/cmdline" LIBVIRTD_FILE="/etc/libvirt/libvirtd.conf" +# Re-use existing password or use the one provided +if [ -f "$PROPS_FILE" ]; then + OLD_PASS=$(sed -n '/keystore.passphrase/p' "$PROPS_FILE" 2>/dev/null | sed 's/keystore.passphrase=//g' 2>/dev/null) + if [ ! -z "${OLD_PASS// }" ]; then + KS_PASS="$OLD_PASS" + else + sed -i "/keystore.passphrase.*/d" $PROPS_FILE 2> /dev/null || true + echo "keystore.passphrase=$KS_PASS" >> $PROPS_FILE + fi +fi + +if [ -f "$KS_FILE" ]; then + keytool -delete -noprompt -alias "$ALIAS" -keystore "$KS_FILE" -storepass "$KS_PASS" > /dev/null 2>&1 || true +fi + +CN=$(hostname --fqdn) +keytool -genkey -storepass "$KS_PASS" -keypass "$KS_PASS" -alias "$ALIAS" -keyalg RSA -validity "$KS_VALIDITY" -dname cn="$CN",ou="cloudstack",o="cloudstack",c="cloudstack" -keystore "$KS_FILE" > /dev/null 2>&1 + # Find keystore password KS_PASS=$(sed -n '/keystore.passphrase/p' "$PROPS_FILE" 2>/dev/null | sed 's/keystore.passphrase=//g' 2>/dev/null) @@ -56,11 +76,6 @@ for caChain in $(ls cloudca.*); do done rm -f cloudca.* -# Stop cloud service in systemvm -if [ "$MODE" == "ssh" ] && [ -f $SYSTEM_FILE ]; then - systemctl stop cloud > /dev/null 2>&1 -fi - # Import private key if available if [ ! -z "${PRIVKEY// }" ]; then echo "$PRIVKEY" > "$PRIVKEY_FILE" @@ -99,10 +114,6 @@ if [ -f "$SYSTEM_FILE" ]; then chmod 644 /usr/local/share/ca-certificates/cloudstack/ca.crt update-ca-certificates > /dev/null 2>&1 || true - # Ensure cloud service is running in systemvm - if [ "$MODE" == "ssh" ]; then - systemctl start cloud > /dev/null 2>&1 - fi fi # Fix file permission diff --git a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 1dcaf7b0b33e..40c6363ce169 100644 --- a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -29,11 +29,11 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.utils.PasswordGenerator; import org.apache.cloudstack.agent.lb.IndirectAgentLB; import org.apache.cloudstack.ca.CAManager; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; +import org.apache.cloudstack.framework.ca.Certificate; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; @@ -1210,8 +1210,11 @@ protected ConsoleProxyManagerImpl() { @Override public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { -// final Certificate certificate = caManager.issueCertificate(null, Arrays.asList(profile.getHostName(), profile.getInstanceName()), -// new ArrayList<>(ipAddressDetails.values()), CAManager.CertValidityPeriod.value(), null); + final Map sshAccessDetails = networkMgr.getSystemVMAccessDetails(profile.getVirtualMachine()); + final Map ipAddressDetails = new HashMap<>(sshAccessDetails); + ipAddressDetails.remove("router.name"); + final Certificate certificate = caManager.issueCertificate(null, Arrays.asList(profile.getHostName(), profile.getInstanceName()), + new ArrayList<>(ipAddressDetails.values()), CAManager.CertValidityPeriod.value(), null); ConsoleProxyVO vm = consoleProxyDao.findById(profile.getId()); Map details = userVmDetailsDao.listDetailsKeyPairs(vm.getId()); vm.setDetails(details); @@ -1281,17 +1284,7 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl buf.append(" dns2=").append(dc.getDns2()); } -// try { -// buf.append(" certificate=").append(CertUtils.x509CertificateToPem(certificate.getClientCertificate())); -// buf.append(" cacertificate=").append(CertUtils.x509CertificatesToPem(certificate.getCaCertificates())); -// if (certificate.getPrivateKey() != null) { -// buf.append(" privatekey=").append(CertUtils.privateKeyToPem(certificate.getPrivateKey())); -// } -// } catch (IOException e) { -// throw new CloudRuntimeException("Failed to transform X509 cert to PEM format", e); -// } - buf.append(" keystore_password=").append(PasswordGenerator.generateRandomPassword(16)); - buf.append(" validity=").append(CAManager.CertValidityPeriod.value()); + VirtualMachineGuru.appendCertificateDetails(buf, certificate); String bootArgs = buf.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug("Boot Args for " + profile + ": " + bootArgs); diff --git a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java index fd4f68bcee04..8f6f12b07649 100644 --- a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java +++ b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java @@ -32,6 +32,7 @@ import java.util.concurrent.Executor; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.ArrayUtils; import org.apache.log4j.xml.DOMConfigurator; import org.eclipse.jetty.websocket.api.Session; @@ -74,6 +75,7 @@ public class ConsoleProxy { static boolean standaloneStart = false; static String encryptorPassword = "Dummy"; + static final String[] skipProperties = new String[]{"certificate", "cacertificate", "keystore_password", "privatekey"}; private static void configLog4j() { final ClassLoader loader = Thread.currentThread().getContextClassLoader(); @@ -108,7 +110,9 @@ private static void configLog4j() { private static void configProxy(Properties conf) { s_logger.info("Configure console proxy..."); for (Object key : conf.keySet()) { - s_logger.info("Property " + (String)key + ": " + conf.getProperty((String)key)); + if (!ArrayUtils.contains(skipProperties, key)) { + s_logger.info("Property " + (String)key + ": " + conf.getProperty((String)key)); + } } String s = conf.getProperty("consoleproxy.httpListenPort"); @@ -247,7 +251,9 @@ public static void startWithContext(Properties conf, Object context, byte[] ksBi if (conf != null) { for (Object key : conf.keySet()) { - s_logger.info("Context property " + (String)key + ": " + conf.getProperty((String)key)); + if (!ArrayUtils.contains(skipProperties, key)) { + s_logger.info("Context property " + (String) key + ": " + conf.getProperty((String) key)); + } } } diff --git a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java index 3a91457fe66c..15a12723f2e8 100644 --- a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java +++ b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java @@ -31,11 +31,13 @@ import javax.naming.ConfigurationException; import org.apache.cloudstack.agent.lb.IndirectAgentLB; +import org.apache.cloudstack.ca.CAManager; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; +import org.apache.cloudstack.framework.ca.Certificate; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; @@ -245,6 +247,8 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar private ImageStoreDetailsUtil imageStoreDetailsUtil; @Inject private IndirectAgentLB indirectAgentLB; + @Inject + private CAManager caManager; private long _capacityScanInterval = DEFAULT_CAPACITY_SCAN_INTERVAL_IN_MILLISECONDS; private int _secStorageVmMtuSize; @@ -1072,6 +1076,12 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl return false; } + final Map sshAccessDetails = _networkMgr.getSystemVMAccessDetails(profile.getVirtualMachine()); + final Map ipAddressDetails = new HashMap<>(sshAccessDetails); + ipAddressDetails.remove("router.name"); + final Certificate certificate = caManager.issueCertificate(null, Arrays.asList(profile.getHostName(), profile.getInstanceName()), + new ArrayList<>(ipAddressDetails.values()), CAManager.CertValidityPeriod.value(), null); + StringBuilder buf = profile.getBootArgsBuilder(); buf.append(" template=domP type=secstorage"); buf.append(" host=").append(com.cloud.utils.StringUtils.toCSVList(indirectAgentLB.getManagementServerList(dest.getHost().getId(), dest.getDataCenter().getId(), null))); @@ -1157,6 +1167,7 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl String nfsVersion = imageStoreDetailsUtil != null ? imageStoreDetailsUtil.getNfsVersion(secStore.getId()) : null; buf.append(" nfsVersion=").append(nfsVersion); + VirtualMachineGuru.appendCertificateDetails(buf, certificate); String bootArgs = buf.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug(String.format("Boot args for machine profile [%s]: [%s].", profile.toString(), bootArgs)); diff --git a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config index 5a50fe850079..15da63e93c6b 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config +++ b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config @@ -55,7 +55,7 @@ patch() { eval $(validate_checksums $md5file $oldpatchfile) if [ "$oldmd5" == "$newmd5" ] && [ -d /usr/local/cloud/systemvm ] && [ "$(ls -A /usr/local/cloud/systemvm)" ]; then - log_it "Checksum matches, do need to patch" + log_it "Checksum matches, no need to patch" return 0 fi diff --git a/systemvm/debian/opt/cloud/bin/setup/common.sh b/systemvm/debian/opt/cloud/bin/setup/common.sh index 75c8f3cee755..be0b1c46b890 100755 --- a/systemvm/debian/opt/cloud/bin/setup/common.sh +++ b/systemvm/debian/opt/cloud/bin/setup/common.sh @@ -593,6 +593,17 @@ routing_svcs() { fi } +setup_certificates() { + certificate=$(echo "$CERTIFICATE" | base64 -d) + cacertificate=$(echo "$CACERTIFICATE" | base64 -d) + privatekey=$(echo "$PRIVATEKEY" | base64 -d) + kspass=$(echo "$KEYSTORE_PSSWD"| base64 -d) + ksvalidity="$KS_VALIDITY" + /opt/cloud/bin/keystore-cert-import /usr/local/cloud/systemvm/conf/agent.properties $kspass $ksvalidity \ + /usr/local/cloud/systemvm/conf/cloud.jks ssh /usr/local/cloud/systemvm/conf/cloud.crt \ + $certificate /usr/local/cloud/systemvm/conf/cloud.ca.crt $cacertificate /usr/local/cloud/systemvm/conf/cloud.key $privatekey +} + parse_cmd_line() { CMDLINE=$(cat /var/cache/cloud/cmdline) TYPE="unknown" @@ -766,7 +777,16 @@ parse_cmd_line() { export KEYSTORE_PSSWD=$VALUE ;; validity) - export VALIDITY=$VALUE + export KS_VALIDITY=$VALUE + ;; + certificate) + export CERTIFICATE=$VALUE + ;; + cacertificate) + export CACERTIFICATE=$VALUE + ;; + privatekey) + export PRIVATEKEY=$VALUE ;; esac done diff --git a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh index ec45b7ffc942..324f92e90859 100755 --- a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh +++ b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh @@ -36,6 +36,8 @@ setup_console_proxy() { enable_fwding 0 enable_irqbalance 0 rm -f /etc/logrotate.d/cloud + + setup_certificates } setup_console_proxy diff --git a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh index 3b21ed5cae17..a34e671ba948 100755 --- a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh +++ b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh @@ -66,6 +66,7 @@ CORS setup_ntp rm -f /etc/logrotate.d/cloud + setup_certificates } setup_secstorage From 9fef1818195ca53ff7fc7c7b148c909133dca177 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Wed, 29 Dec 2021 17:33:31 +0530 Subject: [PATCH 08/68] Commit comprises of the following changes: - Use restart network/VPC API to patch routers - use livePatch API support patching of only cpvm/ssvm - add timeout to the keystore setup/import script --- .../main/java/com/cloud/agent/AgentShell.java | 8 +-- .../com/cloud/network/NetworkService.java | 2 +- .../com/cloud/network/vpc/VpcService.java | 2 +- .../apache/cloudstack/api/ApiConstants.java | 1 + .../user/network/RestartNetworkCmd.java | 5 ++ .../api/command/user/vpc/RestartVPCCmd.java | 5 ++ .../service/NetworkOrchestrationService.java | 2 +- .../orchestration/NetworkOrchestrator.java | 29 ++++++++-- .../com/cloud/vm/dao/ConsoleProxyDaoImpl.java | 2 +- .../LibvirtPatchSystemVmCommandWrapper.java | 2 +- .../vmware/resource/VmwareResource.java | 10 ++-- .../CitrixPatchSystemVmCommandWrapper.java | 1 - .../com/cloud/network/NetworkServiceImpl.java | 10 +++- .../VirtualNetworkApplianceManagerImpl.java | 4 +- .../com/cloud/network/vpc/VpcManagerImpl.java | 17 ++++-- .../com/cloud/server/ManagementServer.java | 3 + .../cloud/server/ManagementServerImpl.java | 58 ++++++++++++++++--- .../com/cloud/vpc/MockNetworkManagerImpl.java | 4 +- .../opt/cloud/bin/setup/consoleproxy.sh | 5 +- .../debian/opt/cloud/bin/setup/secstorage.sh | 5 +- systemvm/patch-sysvms.sh | 19 +++--- .../java/com/cloud/utils/script/Script.java | 2 +- 22 files changed, 144 insertions(+), 52 deletions(-) diff --git a/agent/src/main/java/com/cloud/agent/AgentShell.java b/agent/src/main/java/com/cloud/agent/AgentShell.java index 7d395dff9591..28e38e4cdddb 100644 --- a/agent/src/main/java/com/cloud/agent/AgentShell.java +++ b/agent/src/main/java/com/cloud/agent/AgentShell.java @@ -423,13 +423,13 @@ private void launchAgentFromClassInfo(String resourceClassNames) throws Configur } catch (final ClassNotFoundException e) { throw new ConfigurationException("Resource class not found: " + name + " due to: " + e.toString()); } catch (final SecurityException e) { - throw new ConfigurationException("Security excetion when loading resource: " + name + " due to: " + e.toString()); + throw new ConfigurationException("Security exception when loading resource: " + name + " due to: " + e.toString()); } catch (final NoSuchMethodException e) { - throw new ConfigurationException("Method not found excetion when loading resource: " + name + " due to: " + e.toString()); + throw new ConfigurationException("Method not found exception when loading resource: " + name + " due to: " + e.toString()); } catch (final IllegalArgumentException e) { - throw new ConfigurationException("Illegal argument excetion when loading resource: " + name + " due to: " + e.toString()); + throw new ConfigurationException("Illegal argument exception when loading resource: " + name + " due to: " + e.toString()); } catch (final InstantiationException e) { - throw new ConfigurationException("Instantiation excetion when loading resource: " + name + " due to: " + e.toString()); + throw new ConfigurationException("Instantiation exception when loading resource: " + name + " due to: " + e.toString()); } catch (final IllegalAccessException e) { throw new ConfigurationException("Illegal access exception when loading resource: " + name + " due to: " + e.toString()); } catch (final InvocationTargetException e) { diff --git a/api/src/main/java/com/cloud/network/NetworkService.java b/api/src/main/java/com/cloud/network/NetworkService.java index 297bcbdc8a8a..f37dd88ffed5 100644 --- a/api/src/main/java/com/cloud/network/NetworkService.java +++ b/api/src/main/java/com/cloud/network/NetworkService.java @@ -72,7 +72,7 @@ IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long ne boolean deleteNetwork(long networkId, boolean forced); - boolean restartNetwork(Long networkId, boolean cleanup, boolean makeRedundant, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; + boolean restartNetwork(Long networkId, boolean cleanup, boolean makeRedundant, boolean livePatch, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; boolean restartNetwork(RestartNetworkCmd cmd) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; diff --git a/api/src/main/java/com/cloud/network/vpc/VpcService.java b/api/src/main/java/com/cloud/network/vpc/VpcService.java index d7c83f91678e..32c697a000da 100644 --- a/api/src/main/java/com/cloud/network/vpc/VpcService.java +++ b/api/src/main/java/com/cloud/network/vpc/VpcService.java @@ -136,7 +136,7 @@ public Pair, Integer> listVpcs(Long id, String vpcName, Stri */ boolean restartVpc(RestartVPCCmd cmd) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; - boolean restartVpc(Long networkId, boolean cleanup, boolean makeRedundant, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; + boolean restartVpc(Long networkId, boolean cleanup, boolean makeRedundant, boolean livePatch, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; /** * Returns a Private gateway found in the VPC by id diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index 94e6a7deeb0f..cd2572467ab2 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -33,6 +33,7 @@ public class ApiConstants { public static final String USER_API_KEY = "userapikey"; public static final String APPLIED = "applied"; public static final String LIST_LB_VMIPS = "lbvmips"; + public static final String LIVE_PATCH = "livepatch"; public static final String AVAILABLE = "available"; public static final String BACKUP_ID = "backupid"; public static final String BACKUP_OFFERING_NAME = "backupofferingname"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java index dbcdb8f88846..445130c4c333 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java @@ -59,6 +59,9 @@ public class RestartNetworkCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.MAKEREDUNDANT, type = CommandType.BOOLEAN, required = false, description = "Turn the network into a network with redundant routers.", since = "4.11.1") private Boolean makeRedundant = false; + @Parameter(name = ApiConstants.LIVE_PATCH, type = CommandType.BOOLEAN, required = false, description = "Live Patch the router before restarting it", since = "4.16.1") + private Boolean livePatch = false; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -80,6 +83,8 @@ public Boolean getMakeRedundant() { return makeRedundant; } + public Boolean getLivePatch() { return livePatch; } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java index aade0c2886a5..0e9689816471 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java @@ -54,6 +54,9 @@ public class RestartVPCCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.MAKEREDUNDANT, type = CommandType.BOOLEAN, required = false, description = "Turn a single VPC into a redundant one.") private Boolean makeredundant = false; + @Parameter(name = ApiConstants.LIVE_PATCH, type = CommandType.BOOLEAN, required = false, description = "Live Patch the router before restarting it", since = "4.16.1") + private Boolean livePatch = false; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -70,6 +73,8 @@ public Boolean getMakeredundant() { return makeredundant; } + public Boolean getLivePatch() { return livePatch; } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java index 1673575780cb..16ddfa6ebead 100644 --- a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java @@ -251,7 +251,7 @@ NicProfile createNicForVm(Network network, NicProfile requested, ReservationCont NetworkProfile convertNetworkToNetworkProfile(long networkId); - boolean restartNetwork(Long networkId, Account callerAccount, User callerUser, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException, + boolean restartNetwork(Long networkId, Account callerAccount, User callerUser, boolean cleanup, boolean livePatch) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; boolean shutdownNetworkElementsAndResources(ReservationContext context, boolean b, Network network); diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index e6a95f41f0c5..72073e92484f 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -38,6 +38,7 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.server.ManagementServer; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.annotation.AnnotationService; import org.apache.cloudstack.annotation.dao.AnnotationDao; @@ -305,7 +306,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra @Inject VMNetworkMapDao _vmNetworkMapDao; @Inject - DomainRouterDao _routerDao; + DomainRouterDao routerDao; @Inject RemoteAccessVpnDao _remoteAccessVpnDao; @Inject @@ -318,6 +319,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra ResourceManager resourceManager; @Inject private AnnotationDao annotationDao; + @Inject + public ManagementServer mgr; List networkGurus; @@ -1622,7 +1625,7 @@ public boolean canUpdateInSequence(Network network, boolean forced){ throw new UnsupportedOperationException("Cannot update the network resources in sequence when providers other than virtualrouter are used"); } //check if routers are in correct state before proceeding with the update - List routers = _routerDao.listByNetworkAndRole(network.getId(), VirtualRouter.Role.VIRTUAL_ROUTER); + List routers = routerDao.listByNetworkAndRole(network.getId(), VirtualRouter.Role.VIRTUAL_ROUTER); for (DomainRouterVO router : routers){ if (router.getRedundantState() == VirtualRouter.RedundantState.UNKNOWN) { if (!forced) { @@ -3273,7 +3276,7 @@ public boolean startNetwork(final long networkId, final DeployDestination dest, } @Override - public boolean restartNetwork(final Long networkId, final Account callerAccount, final User callerUser, final boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException, + public boolean restartNetwork(final Long networkId, final Account callerAccount, final User callerUser, final boolean cleanup, final boolean livePatch) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { boolean status = true; boolean restartRequired = false; @@ -3292,6 +3295,20 @@ public boolean restartNetwork(final Long networkId, final Account callerAccount, } setRestartRequired(network, restartRequired); return status; + } else if (livePatch) { + List domainRouters = routerDao.listByNetworkAndRole(network.getId(), VirtualRouter.Role.VIRTUAL_ROUTER); + for (DomainRouterVO router: domainRouters) { + try { + VMInstanceVO instanceVO = _vmDao.findById(router.getId()); + Pair patched = mgr.updateSystemVM(instanceVO, true); + if (patched.first()) { + s_logger.info(String.format("Successfully patched router %s", router)); + } + } catch (CloudRuntimeException e) { + throw new CloudRuntimeException(String.format("Failed to live patch router: %s", router), e); + } + + } } s_logger.debug("Implementing the network " + network + " elements and resources as a part of network restart without cleanup"); @@ -3401,10 +3418,10 @@ private boolean rollingRestartRouters(final NetworkVO network, final NetworkOffe return false; } s_logger.debug("Performing rolling restart of routers of network " + network); - destroyExpendableRouters(_routerDao.findByNetwork(network.getId()), context); + destroyExpendableRouters(routerDao.findByNetwork(network.getId()), context); final List providersToImplement = getNetworkProviders(network.getId()); - final List oldRouters = _routerDao.findByNetwork(network.getId()); + final List oldRouters = routerDao.findByNetwork(network.getId()); // Deploy a new router if (oldRouters.size() > 0) { @@ -3436,7 +3453,7 @@ private boolean rollingRestartRouters(final NetworkVO network, final NetworkOffe implementNetworkElementsAndResources(dest, context, network, offering); } - return areRoutersRunning(_routerDao.findByNetwork(network.getId())); + return areRoutersRunning(routerDao.findByNetwork(network.getId())); } private void setRestartRequired(final NetworkVO network, final boolean restartRequired) { diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/ConsoleProxyDaoImpl.java b/engine/schema/src/main/java/com/cloud/vm/dao/ConsoleProxyDaoImpl.java index 36ff74b11b37..dcf6505ce221 100644 --- a/engine/schema/src/main/java/com/cloud/vm/dao/ConsoleProxyDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/ConsoleProxyDaoImpl.java @@ -52,7 +52,7 @@ public class ConsoleProxyDaoImpl extends GenericDaoBase im + " AS runningVm ON c.id = runningVm.proxy_id WHERE i.state='Running' " + " GROUP BY c.id"; // - // query SQL for returnning running VM count at data center basis + // query SQL for returning running VM count at data center basis // private static final String DATACENTER_VM_MATRIX = "SELECT d.id, d.name, count(v.id) AS count" + " FROM data_center AS d LEFT JOIN vm_instance AS v ON v.data_center_id=d.id " diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java index 5fac33ebec22..b2d64393c111 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java @@ -72,7 +72,7 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR Pair patchResult = null; try { patchResult = SshHelper.sshExecute(controlIp, sshPort, "root", - pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 60000); + pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 600000); } catch (Exception e) { return new PatchSystemVmAnswer(cmd, e.getMessage()); } diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index f258f6a6f8e5..6dab0721e86c 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -470,7 +470,9 @@ public Answer executeRequest(Command cmd) { mbean.addProp("Name", cmd.getClass().getSimpleName()); Class clz = cmd.getClass(); - if (cmd instanceof NetworkElementCommand) { + if (clz == PatchSystemVmCommand.class) { + answer = execute((PatchSystemVmCommand) cmd); + } else if (cmd instanceof NetworkElementCommand) { return _vrResource.executeRequest((NetworkElementCommand) cmd); } else if (clz == ReadyCommand.class) { answer = execute((ReadyCommand) cmd); @@ -595,9 +597,7 @@ public Answer executeRequest(Command cmd) { answer = execute((SetupPersistentNetworkCommand) cmd); } else if (clz == GetVmVncTicketCommand.class) { answer = execute((GetVmVncTicketCommand) cmd); - } else if (clz == PatchSystemVmCommand.class) { - answer = execute((PatchSystemVmCommand) cmd); - } else { + } else { answer = Answer.createUnsupportedCommandAnswer(cmd); } @@ -687,7 +687,7 @@ private Answer execute(PatchSystemVmCommand cmd) { Pair patchResult = null; try { patchResult = SshHelper.sshExecute(controlIp, DefaultDomRSshPort, "root", - pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 60000); + pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 600000); } catch (Exception e) { return new PatchSystemVmAnswer(cmd, e.getMessage()); } diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java index a6b183f9d11e..883c9378aa0c 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java @@ -48,7 +48,6 @@ public Answer execute(PatchSystemVmCommand command, CitrixResourceBase serverRes try { result = getSystemVmVersionAndChecksum(serverResource, controlIp); serverResource.copyPatchFilesToVR(controlIp, "/home/cloud"); - //FileUtil.scpPatchFiles(controlIp, "/home/cloud", sshPort, pemFile, serverResource.newSrcFiles, CitrixResourceBase.BASEPATH); } catch (CloudRuntimeException e) { return new PatchSystemVmAnswer(command, e.getMessage()); } diff --git a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java index f501c8ec37ba..66ab5c970041 100644 --- a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java @@ -2031,7 +2031,7 @@ public boolean deleteNetwork(long networkId, boolean forced) { @Override @ActionEvent(eventType = EventTypes.EVENT_NETWORK_RESTART, eventDescription = "restarting network", async = true) - public boolean restartNetwork(Long networkId, boolean cleanup, boolean makeRedundant, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { + public boolean restartNetwork(Long networkId, boolean cleanup, boolean makeRedundant, boolean livePatch, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { NetworkVO network = _networksDao.findById(networkId); if (network == null) { throwInvalidIdException("Network with specified id doesn't exist", networkId.toString(), "networkId"); @@ -2061,7 +2061,10 @@ public boolean restartNetwork(Long networkId, boolean cleanup, boolean makeRedun cleanup = true; } - boolean success = _networkMgr.restartNetwork(networkId, callerAccount, user, cleanup); + if (cleanup) { + livePatch = false; + } + boolean success = _networkMgr.restartNetwork(networkId, callerAccount, user, cleanup, livePatch); if (success) { s_logger.debug("Network id=" + networkId + " is restarted successfully."); } else { @@ -2078,8 +2081,9 @@ public boolean restartNetwork(RestartNetworkCmd cmd) throws ConcurrentOperationE Long networkId = cmd.getNetworkId(); boolean cleanup = cmd.getCleanup(); boolean makeRedundant = cmd.getMakeRedundant(); + boolean livePatch = cmd.getLivePatch(); User callerUser = _accountMgr.getActiveUser(CallContext.current().getCallingUserId()); - return restartNetwork(networkId, cleanup, makeRedundant, callerUser); + return restartNetwork(networkId, cleanup, makeRedundant, livePatch, callerUser); } @Override diff --git a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 40d5e677e500..90598cfbfdfa 100644 --- a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -1267,7 +1267,7 @@ private boolean restartVpcInDomainRouter(DomainRouterJoinVO router, User user) { ActionEventUtils.onActionEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, Domain.ROOT_DOMAIN, EventTypes.EVENT_ROUTER_HEALTH_CHECKS, "Recreating router " + router.getUuid() + " by restarting VPC " + router.getVpcUuid()); - return vpcService.restartVpc(router.getVpcId(), true, false, user); + return vpcService.restartVpc(router.getVpcId(), true, false, false, user); } catch (Exception e) { s_logger.error("Failed to restart VPC for router recreation " + router.getVpcName() + " ,router " + router.getUuid(), e); @@ -1291,7 +1291,7 @@ private boolean restartGuestNetworkInDomainRouter(DomainRouterJoinVO router, Use ActionEventUtils.onActionEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, Domain.ROOT_DOMAIN, EventTypes.EVENT_ROUTER_HEALTH_CHECKS, "Recreating router " + router.getUuid() + " by restarting network " + router.getNetworkUuid()); - return networkService.restartNetwork(router.getNetworkId(), true, false, user); + return networkService.restartNetwork(router.getNetworkId(), true, false, false, user); } catch (Exception e) { s_logger.error("Failed to restart network " + router.getNetworkName() + " for router recreation " + router.getNetworkName(), e); diff --git a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java index 5752da2bf917..a2bad3d6f791 100644 --- a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java @@ -1712,13 +1712,14 @@ public boolean restartVpc(final RestartVPCCmd cmd) throws ConcurrentOperationExc final long vpcId = cmd.getId(); final boolean cleanUp = cmd.getCleanup(); final boolean makeRedundant = cmd.getMakeredundant(); + final boolean livePatch = cmd.getLivePatch(); final User callerUser = _accountMgr.getActiveUser(CallContext.current().getCallingUserId()); - return restartVpc(vpcId, cleanUp, makeRedundant, callerUser); + return restartVpc(vpcId, cleanUp, makeRedundant, livePatch, callerUser); } @Override @ActionEvent(eventType = EventTypes.EVENT_VPC_RESTART, eventDescription = "restarting vpc") - public boolean restartVpc(Long vpcId, boolean cleanUp, boolean makeRedundant, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { + public boolean restartVpc(Long vpcId, boolean cleanUp, boolean makeRedundant, boolean livePatch, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { Vpc vpc = getActiveVpc(vpcId); if (vpc == null) { final InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find Enabled VPC by id specified"); @@ -1761,7 +1762,11 @@ public boolean restartVpc(Long vpcId, boolean cleanUp, boolean makeRedundant, Us return true; } - restartVPCNetworks(vpcId, callerAccount, user, cleanUp); + if (cleanUp) { + livePatch = false; + } + + restartVPCNetworks(vpcId, callerAccount, user, cleanUp, livePatch); s_logger.debug("Starting VPC " + vpc + " as a part of VPC restart process without cleanup"); if (!startVpc(vpcId, false)) { @@ -1779,11 +1784,11 @@ public boolean restartVpc(Long vpcId, boolean cleanUp, boolean makeRedundant, Us } } - private void restartVPCNetworks(long vpcId, Account callerAccount, User callerUser, boolean cleanUp) throws InsufficientCapacityException, ResourceUnavailableException { + private void restartVPCNetworks(long vpcId, Account callerAccount, User callerUser, boolean cleanUp, boolean livePatch) throws InsufficientCapacityException, ResourceUnavailableException { List networks = _ntwkModel.listNetworksByVpc(vpcId); for (Network network: networks) { - if (network.isRestartRequired()) { - _ntwkMgr.restartNetwork(network.getId(), callerAccount, callerUser, cleanUp); + if (network.isRestartRequired() || livePatch) { + _ntwkMgr.restartNetwork(network.getId(), callerAccount, callerUser, cleanUp, livePatch); } } } diff --git a/server/src/main/java/com/cloud/server/ManagementServer.java b/server/src/main/java/com/cloud/server/ManagementServer.java index 4e58a4f55765..7ecb66503732 100644 --- a/server/src/main/java/com/cloud/server/ManagementServer.java +++ b/server/src/main/java/com/cloud/server/ManagementServer.java @@ -22,6 +22,7 @@ import com.cloud.storage.GuestOSVO; import com.cloud.utils.Pair; import com.cloud.utils.component.PluggableService; +import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; /** @@ -67,4 +68,6 @@ public interface ManagementServer extends ManagementService, PluggableService { public long getMemoryOrCpuCapacityByHost(Long hostId, short capacityType); + Pair updateSystemVM(VMInstanceVO systemVM, boolean forced); + } diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index 2a0734d7ec3a..03a806500de2 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -44,14 +44,21 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; import com.cloud.agent.api.PatchSystemVmAnswer; import com.cloud.agent.api.PatchSystemVmCommand; import com.cloud.agent.api.routing.NetworkElementCommand; +import com.cloud.agent.manager.Commands; import com.cloud.dc.DomainVlanMapVO; import com.cloud.dc.dao.DomainVlanMapDao; import com.cloud.exception.AgentUnavailableException; import com.cloud.network.Networks; +import com.cloud.utils.db.UUIDManager; +import com.cloud.utils.fsm.StateMachine2; +import com.cloud.vm.DomainRouterVO; import com.cloud.vm.NicVO; +import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.NicDao; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.affinity.AffinityGroupProcessor; @@ -766,12 +773,14 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServer, Configurable { public static final Logger s_logger = Logger.getLogger(ManagementServerImpl.class.getName()); + protected StateMachine2 _stateMachine; static final ConfigKey vmPasswordLength = new ConfigKey("Advanced", Integer.class, "vm.password.length", "6", "Specifies the length of a randomly generated password", false); static final ConfigKey sshKeyLength = new ConfigKey("Advanced", Integer.class, "ssh.key.length", "2048", "Specifies custom SSH key length (bit)", true, ConfigKey.Scope.Global); static final ConfigKey humanReadableSizes = new ConfigKey("Advanced", Boolean.class, "display.human.readable.sizes", "true", "Enables outputting human readable byte sizes to logs and usage records.", false, ConfigKey.Scope.Global); public static final ConfigKey customCsIdentifier = new ConfigKey("Advanced", String.class, "custom.cs.identifier", UUID.randomUUID().toString().split("-")[0].substring(4), "Custom identifier for the cloudstack installation", true, ConfigKey.Scope.Global); - private static final VirtualMachine.Type []systemVmTypes = { VirtualMachine.Type.SecondaryStorageVm, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.DomainRouter }; + private static final VirtualMachine.Type []systemVmTypes = { VirtualMachine.Type.SecondaryStorageVm, VirtualMachine.Type.ConsoleProxy}; + //, VirtualMachine.Type.DomainRouter }; @Inject public AccountManager _accountMgr; @@ -909,10 +918,15 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe private DomainVlanMapDao _domainVlanMapDao; @Inject private NicDao nicDao; + @Inject + DomainRouterDao routerDao; + @Inject + public UUIDManager uuidMgr; private LockControllerListener _lockControllerListener; private final ScheduledExecutorService _eventExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("EventChecker")); private final ScheduledExecutorService _alertExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("AlertChecker")); + private static final int patchCommandTimeout = 600000; private Map _configs; @@ -952,6 +966,7 @@ public void setAffinityGroupProcessors(final List affini public ManagementServerImpl() { setRunLevel(ComponentLifecycle.RUN_LEVEL_APPLICATION_MAINLOOP); + setStateMachine(); } public List getUserAuthenticators() { @@ -1010,6 +1025,10 @@ public boolean configure(final String name, final Map params) th return true; } + private void setStateMachine() { + _stateMachine = VirtualMachine.State.getStateMachine(); + } + @Override public boolean start() { s_logger.info("Startup CloudStack management server..."); @@ -4656,7 +4675,7 @@ public Pair patchSystemVM(PatchSystemVMCmd cmd) { final VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(systemVmId, systemVmTypes); if (systemVm == null) { - throw new InvalidParameterValueException("Unable to find SystemVm with id " + systemVmId); + throw new InvalidParameterValueException(String.format("Unable to find SystemVm with id %s. patchSystemVm API can be used to patch CPVM / SSVM only.", systemVmId)); } return updateSystemVM(systemVm, forced); @@ -4676,7 +4695,7 @@ private String getControlIp(final long systemVmId) { } if (controlIpAddress == null) { - s_logger.warn("Unable to find systemVm's control ip in its attached NICs!. systemVmId: " + systemVmId); + s_logger.warn(String.format("Unable to find systemVm's control ip in its attached NICs!. systemVmId: %s", systemVmId)); VMInstanceVO systemVM = _vmInstanceDao.findById(systemVmId); return systemVM.getPrivateIpAddress(); } @@ -4684,30 +4703,53 @@ private String getControlIp(final long systemVmId) { return controlIpAddress; } - private Pair updateSystemVM(VMInstanceVO systemVM, boolean forced) { + public Pair updateSystemVM(VMInstanceVO systemVM, boolean forced) { + String msg = String.format("Unable to patch SystemVM: %s as it is not in Running state. Please destroy and recreate the SystemVM.", systemVM); + if (systemVM.getState() != State.Running) { + s_logger.error(msg); + return new Pair<>(false, msg); + } return patchSystemVm(systemVM, forced); } + private boolean updateRouterDetails(Long routerId, String scriptVersion, String templateVersion) { + DomainRouterVO router = routerDao.findById(routerId); + if (router == null) { + throw new CloudRuntimeException(String.format("Failed to find router with id: %s", routerId)); + } + router.setTemplateVersion(templateVersion); + router.setScriptsVersion(scriptVersion); + return routerDao.update(routerId, router); + } + private Pair patchSystemVm(VMInstanceVO systemVM, boolean forced) { - PatchSystemVmAnswer answer = new PatchSystemVmAnswer(); + PatchSystemVmAnswer answer; final PatchSystemVmCommand command = new PatchSystemVmCommand(); command.setAccessDetail(NetworkElementCommand.ROUTER_IP, getControlIp(systemVM.getId())); command.setAccessDetail(NetworkElementCommand.ROUTER_NAME, systemVM.getInstanceName()); command.setForced(forced); try { - answer = (PatchSystemVmAnswer) _agentMgr.send(systemVM.getHostId(), command); + Commands cmds = new Commands(Command.OnError.Stop); + cmds.addCommand(command); + Answer[] answers = _agentMgr.send(systemVM.getHostId(), cmds, patchCommandTimeout); + answer = (PatchSystemVmAnswer) answers[0]; if (!answer.getResult()) { String errMsg = String.format("Failed to patch systemVM %s due to %s", systemVM.getInstanceName(), answer.getDetails()); s_logger.error(errMsg); return new Pair<>(false, errMsg); } - } catch (AgentUnavailableException | OperationTimedoutException e) { String errMsg = "SystemVM live patch failed"; s_logger.error(errMsg, e); return new Pair<>(false, String.format("%s due to: %s", errMsg, e.getMessage())); } - s_logger.info(String.format("Successfully patch system VM %s", systemVM.getInstanceName())); + s_logger.info(String.format("Successfully patched system VM %s", systemVM.getInstanceName())); + if (systemVM.getType() == VirtualMachine.Type.DomainRouter) { + boolean updated = updateRouterDetails(systemVM.getId(), answer.getScriptsVersion(), answer.getTemplateVersion()); + if (!updated) { + s_logger.warn("Failed to update router's script and template version details"); + } + } return new Pair<>(true, answer.getDetails()); } diff --git a/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java b/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java index 728effa8b764..e6082adb7d34 100644 --- a/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java @@ -214,7 +214,7 @@ public boolean deleteNetwork(long networkId, boolean forced) { } @Override - public boolean restartNetwork(Long networkId, boolean cleanup, boolean makeRedundant, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { + public boolean restartNetwork(Long networkId, boolean cleanup, boolean makeRedundant, boolean livePatch, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { return false; } @@ -760,7 +760,7 @@ public NetworkProfile convertNetworkToNetworkProfile(long networkId) { * @see com.cloud.network.NetworkManager#restartNetwork(java.lang.Long, com.cloud.user.Account, com.cloud.user.User, boolean) */ @Override - public boolean restartNetwork(Long networkId, Account callerAccount, User callerUser, boolean cleanup) throws ConcurrentOperationException, + public boolean restartNetwork(Long networkId, Account callerAccount, User callerUser, boolean cleanup, boolean livePatch) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { // TODO Auto-generated method stub return false; diff --git a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh index 324f92e90859..f193b4541fe1 100755 --- a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh +++ b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh @@ -37,7 +37,10 @@ setup_console_proxy() { enable_irqbalance 0 rm -f /etc/logrotate.d/cloud - setup_certificates + timeout 600 setup_certificates + if [ $? -gt 0 ]; then + log_it "Failed to setup CA Certificate for $TYPE" + fi } setup_console_proxy diff --git a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh index a34e671ba948..83cdb9f5b3dd 100755 --- a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh +++ b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh @@ -66,7 +66,10 @@ CORS setup_ntp rm -f /etc/logrotate.d/cloud - setup_certificates + timeout 600 setup_certificates + if [ $? -gt 0 ]; then + log_it "Failed to setup CA Certificate for $TYPE" + fi } setup_secstorage diff --git a/systemvm/patch-sysvms.sh b/systemvm/patch-sysvms.sh index 31478d7269ae..ee3c78a6270a 100644 --- a/systemvm/patch-sysvms.sh +++ b/systemvm/patch-sysvms.sh @@ -62,13 +62,18 @@ restart_services() { while IFS= read -r line do echo "$line" - systemctl restart "$line" - sleep 5 - systemctl is-active --quiet "$line" - if [ $? -gt 0 ]; then - echo "Failed to start "$line" service. Patch Failed. Restoring backup" >> $logfile - restore_backup - patchfailed=1 + for svc in ${line}; do + systemctl restart "$svc" + sleep 5 + systemctl is-active --quiet "$svc" + if [ $? -gt 0 ]; then + echo "Failed to start "$svc" service. Patch Failed. Retrying again" >> $logfile + restore_backup + patchfailed=1 + break + fi + done + if [ $patchfailed == 1 ]; then break fi done < "$svcfile" diff --git a/utils/src/main/java/com/cloud/utils/script/Script.java b/utils/src/main/java/com/cloud/utils/script/Script.java index 13845cda3a0a..931e922b597c 100644 --- a/utils/src/main/java/com/cloud/utils/script/Script.java +++ b/utils/src/main/java/com/cloud/utils/script/Script.java @@ -320,7 +320,7 @@ public String call() { try { _logger.trace("Checking exit value of process"); _process.exitValue(); - _logger.trace("Script ran within the alloted time"); + _logger.trace("Script ran within the allocated time"); } catch (IllegalThreadStateException e) { _logger.warn("Interrupting script."); _isTimeOut = true; From bdaa364715237dc38a776f047dccc44837435ea1 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Fri, 31 Dec 2021 14:40:54 +0530 Subject: [PATCH 09/68] remove all references of systemvm.iso --- client/pom.xml | 26 ------------------- debian/cloudstack-common.install | 1 - packaging/centos7/cloud.spec | 2 +- packaging/centos8/cloud.spec | 2 +- packaging/suse15/cloud.spec | 2 +- .../vmware/resource/VmwareResource.java | 6 ----- scripts/vm/hypervisor/xenserver/xcposs/patch | 2 +- .../vm/hypervisor/xenserver/xcpserver/patch | 2 +- .../vm/hypervisor/xenserver/xenserver56/patch | 2 +- .../hypervisor/xenserver/xenserver56fp1/patch | 2 +- .../vm/hypervisor/xenserver/xenserver60/patch | 2 +- .../vm/hypervisor/xenserver/xenserver62/patch | 2 +- .../vm/hypervisor/xenserver/xenserver65/patch | 2 +- scripts/vm/systemvm/injectkeys.sh | 8 ------ .../consoleproxy/ConsoleProxyManagerImpl.java | 2 +- .../cloud/server/ConfigurationServerImpl.java | 5 +--- .../SecondaryStorageManagerImpl.java | 2 +- systemvm/pom.xml | 25 ------------------ tools/appliance/build.sh | 4 +-- 19 files changed, 15 insertions(+), 84 deletions(-) diff --git a/client/pom.xml b/client/pom.xml index eea178b9e1f2..73ccecedf873 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -866,32 +866,6 @@ - - - maven-antrun-plugin - 1.7 - - - - copy-systemvm - process-resources - - run - - - - - - - - - - - - - - diff --git a/debian/cloudstack-common.install b/debian/cloudstack-common.install index 9a9cf3bbc09f..8991abd02042 100644 --- a/debian/cloudstack-common.install +++ b/debian/cloudstack-common.install @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -/usr/share/cloudstack-common/vms/systemvm.iso /usr/share/cloudstack-common/scripts/installer/* /usr/share/cloudstack-common/scripts/network/* /usr/share/cloudstack-common/scripts/storage/* diff --git a/packaging/centos7/cloud.spec b/packaging/centos7/cloud.spec index b248cfc3323e..96915a1660ab 100644 --- a/packaging/centos7/cloud.spec +++ b/packaging/centos7/cloud.spec @@ -602,7 +602,7 @@ pip3 install --upgrade urllib3 %attr(0755,root,root) %{_datadir}/%{name}-common/scripts %attr(0755,root,root) /usr/bin/cloudstack-sccs # TODO: Remove systemvm.iso -%attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso +#%attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso %attr(0644, root, root) %{_datadir}/%{name}-common/vms/agent.zip %attr(0644, root, root) %{_datadir}/%{name}-common/vms/cloud-scripts.tgz %attr(0644, root, root) %{_datadir}/%{name}-common/vms/patch-sysvms.sh diff --git a/packaging/centos8/cloud.spec b/packaging/centos8/cloud.spec index 37a374d57e08..35e0e8d53578 100644 --- a/packaging/centos8/cloud.spec +++ b/packaging/centos8/cloud.spec @@ -590,7 +590,7 @@ pip install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz %attr(0755,root,root) %{_datadir}/%{name}-common/scripts %attr(0755,root,root) /usr/bin/cloudstack-sccs # TODO: Remove systemvm.iso -%attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso +#%attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso %attr(0644, root, root) %{_datadir}/%{name}-common/vms/agent.zip %attr(0644, root, root) %{_datadir}/%{name}-common/vms/cloud-scripts.tgz %attr(0644, root, root) %{_datadir}/%{name}-common/vms/patch-sysvms.sh diff --git a/packaging/suse15/cloud.spec b/packaging/suse15/cloud.spec index 23bce9fc92e1..bfdfa4826a1a 100644 --- a/packaging/suse15/cloud.spec +++ b/packaging/suse15/cloud.spec @@ -584,7 +584,7 @@ pip install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz %attr(0755,root,root) %{_datadir}/%{name}-common/scripts %attr(0755,root,root) /usr/bin/cloudstack-sccs # TODO: Remove systemvm.iso -%attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso +#%attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso %attr(0644, root, root) %{_datadir}/%{name}-common/vms/agent.zip %attr(0644, root, root) %{_datadir}/%{name}-common/vms/cloud-scripts.tgz %attr(0644, root, root) %{_datadir}/%{name}-common/vms/patch-sysvms.sh diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 6dab0721e86c..f759d118db17 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -2130,7 +2130,6 @@ protected StartAnswer execute(StartCommand cmd) { String msg = "secondary storage for dc " + _dcId + " is not ready yet?"; throw new Exception(msg); } - mgr.prepareSecondaryStorageStore(secStoreUrl, secStoreId); ManagedObjectReference morSecDs = prepareSecondaryDatastoreOnHost(secStoreUrl); if (morSecDs == null) { @@ -4463,10 +4462,6 @@ protected Answer execute(PrepareForMigrationCommand cmd) { throw new Exception(msg); } - if (vm.getType() != VirtualMachine.Type.User) { - mgr.prepareSecondaryStorageStore(secStoreUrl, secStoreId); - } - ManagedObjectReference morSecDs = prepareSecondaryDatastoreOnHost(secStoreUrl); if (morSecDs == null) { String msg = "Failed to prepare secondary storage on host, secondary store url: " + secStoreUrl; @@ -7428,7 +7423,6 @@ private List relocateVirtualMachine(final VmwareHypervisorHost h String msg = "secondary storage for dc " + _dcId + " is not ready yet?"; throw new Exception(msg); } - mgr.prepareSecondaryStorageStore(secStoreUrl, secStoreId); ManagedObjectReference morSecDs = prepareSecondaryDatastoreOnSpecificHost(secStoreUrl, targetHyperHost); if (morSecDs == null) { throw new Exception(String.format("Failed to prepare secondary storage on host, secondary store url: %s", secStoreUrl)); diff --git a/scripts/vm/hypervisor/xenserver/xcposs/patch b/scripts/vm/hypervisor/xenserver/xcposs/patch index f855c660d3ce..4686e67fe0a7 100644 --- a/scripts/vm/hypervisor/xenserver/xcposs/patch +++ b/scripts/vm/hypervisor/xenserver/xcposs/patch @@ -31,7 +31,7 @@ vmops=..,0755,/usr/lib/xcp/plugins ovsgre=..,0755,/usr/lib/xcp/plugins ovstunnel=..,0755,/usr/lib/xcp/plugins vmopsSnapshot=..,0755,/usr/lib/xcp/plugins -systemvm.iso=../../../../../vms,0644,/usr/share/xcp/packages/iso/ +#systemvm.iso=../../../../../vms,0644,/usr/share/xcp/packages/iso/ agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xcpserver/patch b/scripts/vm/hypervisor/xenserver/xcpserver/patch index 9768cba296da..da6ce60b7f68 100644 --- a/scripts/vm/hypervisor/xenserver/xcpserver/patch +++ b/scripts/vm/hypervisor/xenserver/xcpserver/patch @@ -31,7 +31,7 @@ NFSSR.py=/opt/xensource/sm vmops=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins -systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xenserver56/patch b/scripts/vm/hypervisor/xenserver/xenserver56/patch index 8a784ae21e64..fd844b4b6b05 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver56/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver56/patch @@ -30,7 +30,7 @@ NFSSR.py=/opt/xensource/sm vmops=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins -systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch b/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch index 93d2e4dee6ec..2a0f4b8aac78 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch @@ -30,7 +30,7 @@ NFSSR.py=/opt/xensource/sm vmops=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins -systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xenserver60/patch b/scripts/vm/hypervisor/xenserver/xenserver60/patch index 0271d06f5cf4..e32be41affa6 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver60/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver60/patch @@ -34,7 +34,7 @@ cloudstack_plugins.conf=..,0644,/etc/xensource cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins -systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xenserver62/patch b/scripts/vm/hypervisor/xenserver/xenserver62/patch index 5fda3aff5514..9bf9b9bdac23 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver62/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver62/patch @@ -35,7 +35,7 @@ cloudstack_plugins.conf=..,0644,/etc/xensource cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins cloud-plugin-storage=..,0755,/etc/xapi.d/plugins -systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xenserver65/patch b/scripts/vm/hypervisor/xenserver/xenserver65/patch index 5fda3aff5514..9bf9b9bdac23 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver65/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver65/patch @@ -35,7 +35,7 @@ cloudstack_plugins.conf=..,0644,/etc/xensource cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins cloud-plugin-storage=..,0755,/etc/xapi.d/plugins -systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/systemvm/injectkeys.sh b/scripts/vm/systemvm/injectkeys.sh index c05d232c0e7c..747fb07c5840 100755 --- a/scripts/vm/systemvm/injectkeys.sh +++ b/scripts/vm/systemvm/injectkeys.sh @@ -24,14 +24,8 @@ set -e TMP=/tmp -MOUNTPATH=${HOME}/systemvm_mnt -TMPDIR=${TMP}/cloud/systemvm umask 022 -clean_up() { - $SUDO umount $MOUNTPATH -} - copy_priv_key() { local newprivkey=$1 diff -q $newprivkey $(dirname $0)/id_rsa.cloud && return 0 @@ -45,8 +39,6 @@ then SUDO="sudo -n " fi -$SUDO mkdir -p $MOUNTPATH - [ $# -ne 1 ] && echo "Usage: $(basename $0) " && exit 3 newprivkey=$1 [ ! -f $newprivkey ] && echo "$(basename $0): Could not open $newprivkey" && exit 3 diff --git a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 40c6363ce169..c97646bd6fbf 100644 --- a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -1284,7 +1284,7 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl buf.append(" dns2=").append(dc.getDns2()); } - VirtualMachineGuru.appendCertificateDetails(buf, certificate); + //VirtualMachineGuru.appendCertificateDetails(buf, certificate); String bootArgs = buf.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug("Boot Args for " + profile + ": " + bootArgs); diff --git a/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java b/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java index b28e3de05592..f6e4d517ea84 100644 --- a/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java @@ -742,13 +742,10 @@ protected void copyPrivateKeyToHosts(String publicKeyPath, String privKeyPath) { s_logger.info("Trying to copy private keys to hosts"); String injectScript = getInjectScript(); String scriptPath = Script.findScript("", injectScript); - String systemVmIsoPath = Script.findScript("", "vms/systemvm.iso"); if (scriptPath == null) { throw new CloudRuntimeException("Unable to find key inject script " + injectScript); } - if (systemVmIsoPath == null) { - throw new CloudRuntimeException("Unable to find systemvm iso vms/systemvm.iso"); - } + Script command = null; if(isOnWindows()) { command = new Script("python", s_logger); diff --git a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java index 15a12723f2e8..a6ce0f4f4dc6 100644 --- a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java +++ b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java @@ -1167,7 +1167,7 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl String nfsVersion = imageStoreDetailsUtil != null ? imageStoreDetailsUtil.getNfsVersion(secStore.getId()) : null; buf.append(" nfsVersion=").append(nfsVersion); - VirtualMachineGuru.appendCertificateDetails(buf, certificate); + //VirtualMachineGuru.appendCertificateDetails(buf, certificate); String bootArgs = buf.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug(String.format("Boot args for machine profile [%s]: [%s].", profile.toString(), bootArgs)); diff --git a/systemvm/pom.xml b/systemvm/pom.xml index 929f948abd1d..69e971b74715 100644 --- a/systemvm/pom.xml +++ b/systemvm/pom.xml @@ -144,31 +144,6 @@ - - org.codehaus.mojo - exec-maven-plugin - 1.2.1 - - - package - - exec - - - - - ${mkisofs} - dist - - -quiet - -r - -o - systemvm.iso - agent.zip - cloud-scripts.tgz - - - diff --git a/tools/appliance/build.sh b/tools/appliance/build.sh index 285d818c0c75..5a97c9dbf6b6 100755 --- a/tools/appliance/build.sh +++ b/tools/appliance/build.sh @@ -348,9 +348,9 @@ function main() { packer_build # process the disk at dist -# kvm_export + kvm_export # ovm_export -# xen_server_export + xen_server_export vmware_export # hyperv_export rm -f "dist/${appliance}" From b923ed2b2a354edabde104b00950f71cfdb4e100 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Mon, 3 Jan 2022 12:59:34 +0530 Subject: [PATCH 10/68] Fix keystore-cert-import invocation + refactor cert timeout in CP/SS VMs --- .../VirtualRoutingResource.java | 6 +- scripts/util/keystore-cert-import | 35 +++++---- .../consoleproxy/ConsoleProxyManagerImpl.java | 2 +- .../discoverer/LibvirtServerDiscoverer.java | 78 ++++++++++--------- .../SecondaryStorageManagerImpl.java | 2 +- .../opt/cloud/bin/setup/consoleproxy.sh | 2 +- .../debian/opt/cloud/bin/setup/secstorage.sh | 2 +- .../main/java/com/cloud/utils/FileUtil.java | 28 ++++--- .../com/cloud/utils/ssh/SSHCmdHelper.java | 4 +- 9 files changed, 85 insertions(+), 74 deletions(-) diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java index 54b9d38a9625..2690ec4c8076 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java @@ -34,6 +34,8 @@ import javax.naming.ConfigurationException; +import com.cloud.utils.PasswordGenerator; +import org.apache.cloudstack.ca.CAManager; import org.apache.cloudstack.ca.SetupCertificateAnswer; import org.apache.cloudstack.ca.SetupCertificateCommand; import org.apache.cloudstack.ca.SetupKeyStoreCommand; @@ -174,11 +176,13 @@ private Answer execute(final SetupKeyStoreCommand cmd) { } private Answer execute(final SetupCertificateCommand cmd) { - final String args = String.format("/usr/local/cloud/systemvm/conf/agent.properties " + + final String args = String.format("/usr/local/cloud/systemvm/conf/agent.properties %s %s " + "/usr/local/cloud/systemvm/conf/%s %s " + "/usr/local/cloud/systemvm/conf/%s \"%s\" " + "/usr/local/cloud/systemvm/conf/%s \"%s\" " + "/usr/local/cloud/systemvm/conf/%s \"%s\"", + PasswordGenerator.generateRandomPassword(16), + CAManager.CertValidityPeriod.value(), KeyStoreUtils.KS_FILENAME, KeyStoreUtils.SSH_MODE, KeyStoreUtils.CERT_FILENAME, diff --git a/scripts/util/keystore-cert-import b/scripts/util/keystore-cert-import index 8e63e9509cc0..7c750a412eb8 100755 --- a/scripts/util/keystore-cert-import +++ b/scripts/util/keystore-cert-import @@ -32,24 +32,25 @@ ALIAS="cloud" SYSTEM_FILE="/var/cache/cloud/cmdline" LIBVIRTD_FILE="/etc/libvirt/libvirtd.conf" -# Re-use existing password or use the one provided -if [ -f "$PROPS_FILE" ]; then - OLD_PASS=$(sed -n '/keystore.passphrase/p' "$PROPS_FILE" 2>/dev/null | sed 's/keystore.passphrase=//g' 2>/dev/null) - if [ ! -z "${OLD_PASS// }" ]; then - KS_PASS="$OLD_PASS" - else - sed -i "/keystore.passphrase.*/d" $PROPS_FILE 2> /dev/null || true - echo "keystore.passphrase=$KS_PASS" >> $PROPS_FILE - fi +if [ ! -f "$LIBVIRTD_FILE" ]; then + # Re-use existing password or use the one provided + if [ -f "$PROPS_FILE" ]; then + OLD_PASS=$(sed -n '/keystore.passphrase/p' "$PROPS_FILE" 2>/dev/null | sed 's/keystore.passphrase=//g' 2>/dev/null) + if [ ! -z "${OLD_PASS// }" ]; then + KS_PASS="$OLD_PASS" + else + sed -i "/keystore.passphrase.*/d" $PROPS_FILE 2> /dev/null || true + echo "keystore.passphrase=$KS_PASS" >> $PROPS_FILE + fi + fi + + if [ -f "$KS_FILE" ]; then + keytool -delete -noprompt -alias "$ALIAS" -keystore "$KS_FILE" -storepass "$KS_PASS" > /dev/null 2>&1 || true + fi + + CN=$(hostname --fqdn) + keytool -genkey -storepass "$KS_PASS" -keypass "$KS_PASS" -alias "$ALIAS" -keyalg RSA -validity "$KS_VALIDITY" -dname cn="$CN",ou="cloudstack",o="cloudstack",c="cloudstack" -keystore "$KS_FILE" > /dev/null 2>&1 fi - -if [ -f "$KS_FILE" ]; then - keytool -delete -noprompt -alias "$ALIAS" -keystore "$KS_FILE" -storepass "$KS_PASS" > /dev/null 2>&1 || true -fi - -CN=$(hostname --fqdn) -keytool -genkey -storepass "$KS_PASS" -keypass "$KS_PASS" -alias "$ALIAS" -keyalg RSA -validity "$KS_VALIDITY" -dname cn="$CN",ou="cloudstack",o="cloudstack",c="cloudstack" -keystore "$KS_FILE" > /dev/null 2>&1 - # Find keystore password KS_PASS=$(sed -n '/keystore.passphrase/p' "$PROPS_FILE" 2>/dev/null | sed 's/keystore.passphrase=//g' 2>/dev/null) diff --git a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index c97646bd6fbf..40c6363ce169 100644 --- a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -1284,7 +1284,7 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl buf.append(" dns2=").append(dc.getDns2()); } - //VirtualMachineGuru.appendCertificateDetails(buf, certificate); + VirtualMachineGuru.appendCertificateDetails(buf, certificate); String bootArgs = buf.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug("Boot Args for " + profile + ": " + bootArgs); diff --git a/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java b/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java index 818c14f5b25f..a67925bbef45 100644 --- a/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java +++ b/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java @@ -16,26 +16,6 @@ // under the License. package com.cloud.hypervisor.kvm.discoverer; -import java.net.InetAddress; -import java.net.URI; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import javax.inject.Inject; -import javax.naming.ConfigurationException; - -import org.apache.cloudstack.agent.lb.IndirectAgentLB; -import org.apache.cloudstack.ca.CAManager; -import org.apache.cloudstack.ca.SetupCertificateCommand; -import org.apache.cloudstack.direct.download.DirectDownloadManager; -import org.apache.cloudstack.framework.ca.Certificate; -import org.apache.cloudstack.utils.security.KeyStoreUtils; -import org.apache.log4j.Logger; - import com.cloud.agent.AgentManager; import com.cloud.agent.Listener; import com.cloud.agent.api.AgentControlAnswer; @@ -68,6 +48,24 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.ssh.SSHCmdHelper; import com.trilead.ssh2.Connection; +import org.apache.cloudstack.agent.lb.IndirectAgentLB; +import org.apache.cloudstack.ca.CAManager; +import org.apache.cloudstack.ca.SetupCertificateCommand; +import org.apache.cloudstack.direct.download.DirectDownloadManager; +import org.apache.cloudstack.framework.ca.Certificate; +import org.apache.cloudstack.utils.security.KeyStoreUtils; +import org.apache.log4j.Logger; + +import javax.inject.Inject; +import javax.naming.ConfigurationException; +import java.net.InetAddress; +import java.net.URI; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; import static com.cloud.configuration.ConfigurationManagerImpl.ADD_HOST_ON_SERVICE_RESTART_KVM; @@ -163,6 +161,7 @@ private void setupAgentSecurity(final Connection sshConnection, final String age validityPeriod = 1; } + String keystorePassword = PasswordGenerator.generateRandomPassword(16); final SSHCmdHelper.SSHCmdResult keystoreSetupResult = SSHCmdHelper.sshExecuteCmdWithResult(sshConnection, String.format("sudo /usr/share/cloudstack-common/scripts/util/%s " + "/etc/cloudstack/agent/agent.properties " + @@ -171,7 +170,7 @@ private void setupAgentSecurity(final Connection sshConnection, final String age "/etc/cloudstack/agent/%s", KeyStoreUtils.KS_SETUP_SCRIPT, KeyStoreUtils.KS_FILENAME, - PasswordGenerator.generateRandomPassword(16), + keystorePassword, validityPeriod, KeyStoreUtils.CSR_FILENAME)); @@ -186,21 +185,23 @@ private void setupAgentSecurity(final Connection sshConnection, final String age final SetupCertificateCommand certificateCommand = new SetupCertificateCommand(certificate); final SSHCmdHelper.SSHCmdResult setupCertResult = SSHCmdHelper.sshExecuteCmdWithResult(sshConnection, - String.format("sudo /usr/share/cloudstack-common/scripts/util/%s " + - "/etc/cloudstack/agent/agent.properties " + - "/etc/cloudstack/agent/%s %s " + - "/etc/cloudstack/agent/%s \"%s\" " + - "/etc/cloudstack/agent/%s \"%s\" " + - "/etc/cloudstack/agent/%s \"%s\"", - KeyStoreUtils.KS_IMPORT_SCRIPT, - KeyStoreUtils.KS_FILENAME, - KeyStoreUtils.SSH_MODE, - KeyStoreUtils.CERT_FILENAME, - certificateCommand.getEncodedCertificate(), - KeyStoreUtils.CACERT_FILENAME, - certificateCommand.getEncodedCaCertificates(), - KeyStoreUtils.PKEY_FILENAME, - certificateCommand.getEncodedPrivateKey())); + String.format("sudo /usr/share/cloudstack-common/scripts/util/%s " + + "/etc/cloudstack/agent/agent.properties %s %s " + + " /etc/cloudstack/agent/%s %s " + + "/etc/cloudstack/agent/%s \"%s\" " + + "/etc/cloudstack/agent/%s \"%s\" " + + "/etc/cloudstack/agent/%s \"%s\"", + KeyStoreUtils.KS_IMPORT_SCRIPT, + keystorePassword, + validityPeriod, + KeyStoreUtils.KS_FILENAME, + KeyStoreUtils.SSH_MODE, + KeyStoreUtils.CERT_FILENAME, + certificateCommand.getEncodedCertificate(), + KeyStoreUtils.CACERT_FILENAME, + certificateCommand.getEncodedCaCertificates(), + KeyStoreUtils.PKEY_FILENAME, + certificateCommand.getEncodedPrivateKey())); if (setupCertResult != null && !setupCertResult.isSuccess()) { throw new CloudRuntimeException("Failed to setup certificate in the KVM agent's keystore file, please see logs and configure manually!"); @@ -213,7 +214,7 @@ private void setupAgentSecurity(final Connection sshConnection, final String age @Override public Map> - find(long dcId, Long podId, Long clusterId, URI uri, String username, String password, List hostTags) throws DiscoveryException { + find(long dcId, Long podId, Long clusterId, URI uri, String username, String password, List hostTags) throws DiscoveryException { boolean isUefiSupported = false; ClusterVO cluster = _clusterDao.findById(clusterId); @@ -256,6 +257,7 @@ private void setupAgentSecurity(final Connection sshConnection, final String age } } + s_logger.info("PEARL - agent IP: "+ agentIp); sshConnection = new Connection(agentIp, 22); sshConnection.connect(null, 60000, 60000); @@ -473,7 +475,7 @@ public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { String hostOs = ssCmd.getHostDetails().get("Host.OS"); if (!hostOsInCluster.equalsIgnoreCase(hostOs)) { throw new IllegalArgumentException("Can't add host: " + firstCmd.getPrivateIpAddress() + " with hostOS: " + hostOs + " into a cluster," + - "in which there are " + hostOsInCluster + " hosts added"); + "in which there are " + hostOsInCluster + " hosts added"); } } diff --git a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java index a6ce0f4f4dc6..15a12723f2e8 100644 --- a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java +++ b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java @@ -1167,7 +1167,7 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl String nfsVersion = imageStoreDetailsUtil != null ? imageStoreDetailsUtil.getNfsVersion(secStore.getId()) : null; buf.append(" nfsVersion=").append(nfsVersion); - //VirtualMachineGuru.appendCertificateDetails(buf, certificate); + VirtualMachineGuru.appendCertificateDetails(buf, certificate); String bootArgs = buf.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug(String.format("Boot args for machine profile [%s]: [%s].", profile.toString(), bootArgs)); diff --git a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh index f193b4541fe1..eddbc9daf9a0 100755 --- a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh +++ b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh @@ -37,7 +37,7 @@ setup_console_proxy() { enable_irqbalance 0 rm -f /etc/logrotate.d/cloud - timeout 600 setup_certificates + timeout 600 setup_certificates <( setup_certificates ) if [ $? -gt 0 ]; then log_it "Failed to setup CA Certificate for $TYPE" fi diff --git a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh index 83cdb9f5b3dd..c16b53d3cbd9 100755 --- a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh +++ b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh @@ -66,7 +66,7 @@ CORS setup_ntp rm -f /etc/logrotate.d/cloud - timeout 600 setup_certificates + timeout 600 setup_certificates <( setup_certificates ) if [ $? -gt 0 ]; then log_it "Failed to setup CA Certificate for $TYPE" fi diff --git a/utils/src/main/java/com/cloud/utils/FileUtil.java b/utils/src/main/java/com/cloud/utils/FileUtil.java index 2121d3a7ae26..cc44c0b80570 100644 --- a/utils/src/main/java/com/cloud/utils/FileUtil.java +++ b/utils/src/main/java/com/cloud/utils/FileUtil.java @@ -38,18 +38,22 @@ public static void copyfile(File source, File destination) throws IOException { } public static void scpPatchFiles(String controlIp, String destPath, int sshPort, File pemFile, String[] files, String basePath) { - try { - List srcFiles = Arrays.asList(files); - srcFiles = srcFiles.stream() - .map(file -> basePath + file) // Using Lambda notation to update the entries - .collect(Collectors.toList()); - String[] newSrcFiles = srcFiles.toArray(new String[0]); - SshHelper.scpTo(controlIp, sshPort, "root", pemFile, null, - destPath, newSrcFiles, "0755"); - } catch (Exception e) { - String errMsg = "Failed to scp files to system VM"; - s_logger.error(errMsg, e); - throw new CloudRuntimeException(errMsg, e); + String errMsg = "Failed to scp files to system VM"; + List srcFiles = Arrays.asList(files); + srcFiles = srcFiles.stream() + .map(file -> basePath + file) // Using Lambda notation to update the entries + .collect(Collectors.toList()); + String[] newSrcFiles = srcFiles.toArray(new String[0]); + for (int retries = 3; retries > 0; retries--) { + try { + SshHelper.scpTo(controlIp, sshPort, "root", pemFile, null, + destPath, newSrcFiles, "0755"); + return; + } catch (Exception e) { + errMsg += ", retrying"; + s_logger.error(errMsg, e); + } } + throw new CloudRuntimeException(errMsg); } } diff --git a/utils/src/main/java/com/cloud/utils/ssh/SSHCmdHelper.java b/utils/src/main/java/com/cloud/utils/ssh/SSHCmdHelper.java index 41ee2edb4623..6621546859c9 100644 --- a/utils/src/main/java/com/cloud/utils/ssh/SSHCmdHelper.java +++ b/utils/src/main/java/com/cloud/utils/ssh/SSHCmdHelper.java @@ -241,8 +241,8 @@ public static SSHCmdResult sshExecuteCmdOneShot(com.trilead.ssh2.Connection sshC } return result; } catch (Exception e) { - s_logger.debug("Ssh executed failed", e); - throw new SshException("Ssh executed failed " + e.getMessage()); + s_logger.debug("SSH execution failed", e); + throw new SshException("SSH execution failed " + e.getMessage()); } finally { if (sshSession != null) sshSession.close(); From a380f68f9582b5e18973407a5ffefbba59eddb86 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Mon, 3 Jan 2022 16:41:56 +0530 Subject: [PATCH 11/68] fix script timeout --- systemvm/debian/opt/cloud/bin/setup/common.sh | 2 +- systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh | 2 +- systemvm/debian/opt/cloud/bin/setup/secstorage.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/systemvm/debian/opt/cloud/bin/setup/common.sh b/systemvm/debian/opt/cloud/bin/setup/common.sh index be0b1c46b890..3f4817a07795 100755 --- a/systemvm/debian/opt/cloud/bin/setup/common.sh +++ b/systemvm/debian/opt/cloud/bin/setup/common.sh @@ -599,7 +599,7 @@ setup_certificates() { privatekey=$(echo "$PRIVATEKEY" | base64 -d) kspass=$(echo "$KEYSTORE_PSSWD"| base64 -d) ksvalidity="$KS_VALIDITY" - /opt/cloud/bin/keystore-cert-import /usr/local/cloud/systemvm/conf/agent.properties $kspass $ksvalidity \ + timeout 600 /opt/cloud/bin/keystore-cert-import /usr/local/cloud/systemvm/conf/agent.properties $kspass $ksvalidity \ /usr/local/cloud/systemvm/conf/cloud.jks ssh /usr/local/cloud/systemvm/conf/cloud.crt \ $certificate /usr/local/cloud/systemvm/conf/cloud.ca.crt $cacertificate /usr/local/cloud/systemvm/conf/cloud.key $privatekey } diff --git a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh index eddbc9daf9a0..f8fcb51d94cb 100755 --- a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh +++ b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh @@ -37,7 +37,7 @@ setup_console_proxy() { enable_irqbalance 0 rm -f /etc/logrotate.d/cloud - timeout 600 setup_certificates <( setup_certificates ) + setup_certificates if [ $? -gt 0 ]; then log_it "Failed to setup CA Certificate for $TYPE" fi diff --git a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh index c16b53d3cbd9..041853287a34 100755 --- a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh +++ b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh @@ -66,7 +66,7 @@ CORS setup_ntp rm -f /etc/logrotate.d/cloud - timeout 600 setup_certificates <( setup_certificates ) + setup_certificates if [ $? -gt 0 ]; then log_it "Failed to setup CA Certificate for $TYPE" fi From 447ae42d52c14a4191419c8f718d5dcc35c975a7 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Wed, 5 Jan 2022 18:03:28 +0530 Subject: [PATCH 12/68] Refactor cert patching for systemVMs + update keystore-cert-import script + patch-sysvms script + remove patchSysvmCommand from networkelementcommand --- .gitignore | 1 + .../src/main/java/com/cloud/agent/Agent.java | 2 + .../cloud/agent/api/PatchSystemVmCommand.java | 31 ++++++++++- .../com/cloud/agent/api/StartCommand.java | 30 +++++++++++ .../VirtualRoutingResource.java | 10 ++-- .../com/cloud/resource/ServerResource.java | 2 + .../cloud/resource/ServerResourceBase.java | 4 +- .../java/com/cloud/vm/VirtualMachineGuru.java | 2 +- .../cloud/vm/VirtualMachineManagerImpl.java | 45 ++++++++++++++-- .../LibvirtPatchSystemVmCommandWrapper.java | 16 ++++-- .../wrapper/LibvirtStartCommandWrapper.java | 32 ++++++++++++ .../vmware/resource/VmwareResource.java | 16 ++++-- .../resource/CitrixResourceBase.java | 9 +--- .../CitrixNetworkElementCommandWrapper.java | 3 +- .../CitrixPatchSystemVmCommandWrapper.java | 17 +++++-- scripts/util/keystore-cert-import | 47 +++++++++++------ .../consoleproxy/ConsoleProxyManagerImpl.java | 5 +- .../discoverer/LibvirtServerDiscoverer.java | 6 +-- .../cloud/server/ManagementServerImpl.java | 1 + .../apache/cloudstack/ca/CAManagerImpl.java | 17 +++++-- .../com/cloud/consoleproxy/ConsoleProxy.java | 15 +++--- .../SecondaryStorageManagerImpl.java | 5 +- .../opt/cloud/bin/setup/cloud-early-config | 3 ++ systemvm/debian/opt/cloud/bin/setup/common.sh | 10 ++-- .../opt/cloud/bin/setup/consoleproxy.sh | 11 ++-- .../debian/opt/cloud/bin/setup/secstorage.sh | 8 +-- systemvm/patch-sysvms.sh | 51 +++++++++++-------- .../utils/security/KeyStoreUtils.java | 1 + 28 files changed, 300 insertions(+), 100 deletions(-) diff --git a/.gitignore b/.gitignore index b67dc8e6499f..011a4b005dce 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,7 @@ tools/cli/cloudmonkey/precache.py tools/marvin/marvin/cloudstackAPI/ tools/marvin/build/ tools/cli/build/ +tools/appliance/systemvmtemplate/packer_cache/ *.jar *.war *.mar diff --git a/agent/src/main/java/com/cloud/agent/Agent.java b/agent/src/main/java/com/cloud/agent/Agent.java index 4edfb7871a51..2d14b910ad6d 100644 --- a/agent/src/main/java/com/cloud/agent/Agent.java +++ b/agent/src/main/java/com/cloud/agent/Agent.java @@ -763,8 +763,10 @@ private Answer setupAgentCertificate(final SetupCertificateCommand cmd) { throw new CloudRuntimeException("Unable to save received agent client and ca certificates", e); } + String ksPassphrase = _shell.getPersistentProperty(null, KeyStoreUtils.KS_PASSPHRASE_PROPERTY); Script script = new Script(_keystoreCertImportPath, 300000, s_logger); script.add(agentFile.getAbsolutePath()); + script.add(ksPassphrase); script.add(keyStoreFile); script.add(KeyStoreUtils.AGENT_MODE); script.add(certFile); diff --git a/core/src/main/java/com/cloud/agent/api/PatchSystemVmCommand.java b/core/src/main/java/com/cloud/agent/api/PatchSystemVmCommand.java index b9ea2d62963b..29c5baca7f03 100644 --- a/core/src/main/java/com/cloud/agent/api/PatchSystemVmCommand.java +++ b/core/src/main/java/com/cloud/agent/api/PatchSystemVmCommand.java @@ -16,8 +16,12 @@ // under the License. package com.cloud.agent.api; -public class PatchSystemVmCommand extends GetDomRVersionCmd { +import java.util.HashMap; +import java.util.Map; + +public class PatchSystemVmCommand extends Command { boolean forced; + HashMap accessDetails = new HashMap(0); public boolean isForced() { return forced; @@ -26,4 +30,29 @@ public boolean isForced() { public void setForced(boolean forced) { this.forced = forced; } + + public void setAccessDetail(final Map details) { + if (details == null) { + return; + } + for (final Map.Entry detail : details.entrySet()) { + if (detail == null) { + continue; + } + setAccessDetail(detail.getKey(), detail.getValue()); + } + } + + public void setAccessDetail(final String name, final String value) { + accessDetails.put(name, value); + } + + public String getAccessDetail(final String name) { + return accessDetails.get(name); + } + + @Override + public boolean executeInSequence() { + return false; + } } diff --git a/core/src/main/java/com/cloud/agent/api/StartCommand.java b/core/src/main/java/com/cloud/agent/api/StartCommand.java index 24b0ac3787b5..3af11932588e 100644 --- a/core/src/main/java/com/cloud/agent/api/StartCommand.java +++ b/core/src/main/java/com/cloud/agent/api/StartCommand.java @@ -29,6 +29,12 @@ public class StartCommand extends Command { String hostIp; boolean executeInSequence = false; String secondaryStorage; + @LogLevel(LogLevel.Log4jLevel.Off) + private String certificate; + @LogLevel(LogLevel.Log4jLevel.Off) + private String privateKey = ""; + @LogLevel(LogLevel.Log4jLevel.Off) + private String caCertificates; public VirtualMachineTO getVirtualMachine() { return vm; @@ -64,4 +70,28 @@ public String getSecondaryStorage() { public void setSecondaryStorage(String secondary) { this.secondaryStorage = secondary; } + + public void setCertificate(String certificate) { + this.certificate = certificate; + } + + public void setPrivateKey(String privateKey) { + this.privateKey = privateKey; + } + + public void setCaCertificates(String caCertificates) { + this.caCertificates = caCertificates; + } + + public String getCertificate() { + return certificate; + } + + public String getPrivateKey() { + return privateKey; + } + + public String getCaCertificates() { + return caCertificates; + } } diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java index 2690ec4c8076..cddee33ac382 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java @@ -35,7 +35,6 @@ import javax.naming.ConfigurationException; import com.cloud.utils.PasswordGenerator; -import org.apache.cloudstack.ca.CAManager; import org.apache.cloudstack.ca.SetupCertificateAnswer; import org.apache.cloudstack.ca.SetupCertificateCommand; import org.apache.cloudstack.ca.SetupKeyStoreCommand; @@ -176,13 +175,18 @@ private Answer execute(final SetupKeyStoreCommand cmd) { } private Answer execute(final SetupCertificateCommand cmd) { - final String args = String.format("/usr/local/cloud/systemvm/conf/agent.properties %s %s " + + String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + if (!org.apache.commons.lang3.StringUtils.isEmpty(routerName) && (routerName.startsWith("s-") || routerName.startsWith("v-"))) { + _vrDeployer.createFileInVR(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.CERT_FILENAME, cmd.getCertificate()); + _vrDeployer.createFileInVR(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.CACERT_FILENAME, cmd.getCaCertificates()); + _vrDeployer.createFileInVR(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.PKEY_FILENAME, cmd.getPrivateKey()); + } + final String args = String.format("/usr/local/cloud/systemvm/conf/agent.properties %s " + "/usr/local/cloud/systemvm/conf/%s %s " + "/usr/local/cloud/systemvm/conf/%s \"%s\" " + "/usr/local/cloud/systemvm/conf/%s \"%s\" " + "/usr/local/cloud/systemvm/conf/%s \"%s\"", PasswordGenerator.generateRandomPassword(16), - CAManager.CertValidityPeriod.value(), KeyStoreUtils.KS_FILENAME, KeyStoreUtils.SSH_MODE, KeyStoreUtils.CERT_FILENAME, diff --git a/core/src/main/java/com/cloud/resource/ServerResource.java b/core/src/main/java/com/cloud/resource/ServerResource.java index 5571f33bb8a3..f2beb4a1845a 100644 --- a/core/src/main/java/com/cloud/resource/ServerResource.java +++ b/core/src/main/java/com/cloud/resource/ServerResource.java @@ -26,6 +26,7 @@ import com.cloud.agent.api.StartupCommand; import com.cloud.host.Host; import com.cloud.utils.component.Manager; +import org.apache.cloudstack.utils.security.KeyStoreUtils; import java.io.File; @@ -36,6 +37,7 @@ public interface ServerResource extends Manager { String[] srcFiles = new String[] { "agent.zip", "cloud-scripts.tgz" }; String[] newSrcFiles = new String[] { "agent.zip", "cloud-scripts.tgz", "patch-sysvms.sh" }; + String[] certificateFiles = new String[] {KeyStoreUtils.CERT_FILENAME, KeyStoreUtils.CACERT_FILENAME, KeyStoreUtils.PKEY_FILENAME}; String SSHKEYSPATH = "/root/.ssh"; String SSHPRVKEYPATH = SSHKEYSPATH + File.separator + "id_rsa.cloud"; diff --git a/core/src/main/java/com/cloud/resource/ServerResourceBase.java b/core/src/main/java/com/cloud/resource/ServerResourceBase.java index 80057779e249..d8db1fd64605 100644 --- a/core/src/main/java/com/cloud/resource/ServerResourceBase.java +++ b/core/src/main/java/com/cloud/resource/ServerResourceBase.java @@ -310,8 +310,8 @@ public boolean stop() { return true; } - public String calculateCurrentChecksum(String name) { - String cloudScriptsPath = Script.findScript("", "vms/cloud-scripts.tgz"); + public String calculateCurrentChecksum(String name, String path) { + String cloudScriptsPath = Script.findScript("", path); if (cloudScriptsPath == null) { throw new CloudRuntimeException(String.format("Unable to find cloudScripts path, cannot update SystemVM %s", name)); } diff --git a/engine/api/src/main/java/com/cloud/vm/VirtualMachineGuru.java b/engine/api/src/main/java/com/cloud/vm/VirtualMachineGuru.java index d6d7513fd5c6..f8032bf4b0e7 100644 --- a/engine/api/src/main/java/com/cloud/vm/VirtualMachineGuru.java +++ b/engine/api/src/main/java/com/cloud/vm/VirtualMachineGuru.java @@ -80,7 +80,7 @@ static String getEncodedMsPublicKey(String pubKey) { return base64EncodedPublicKey; } - private static String getEncodedString(String certificate) { + public static String getEncodedString(String certificate) { return Base64.getEncoder().encodeToString(certificate.replace("\n", KeyStoreUtils.CERT_NEWLINE_ENCODER).replace(" ", KeyStoreUtils.CERT_SPACE_ENCODER).getBytes(StandardCharsets.UTF_8)); } diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index fdd77d6c23fb..0284d466234c 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -17,6 +17,7 @@ package com.cloud.vm; +import java.io.IOException; import java.net.URI; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -79,6 +80,7 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.cloudstack.utils.identity.ManagementServerNode; +import org.apache.cloudstack.utils.security.CertUtils; import org.apache.cloudstack.vm.UnmanagedVMsManager; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; @@ -551,7 +553,7 @@ public void advanceExpunge(final String vmUuid) throws ResourceUnavailableExcept advanceExpunge(vm); } - private boolean expungeCommandCanBypassHostMaintenance(VirtualMachine vm) { + private boolean isValidSystemVMType(VirtualMachine vm) { return VirtualMachine.Type.SecondaryStorageVm.equals(vm.getType()) || VirtualMachine.Type.ConsoleProxy.equals(vm.getType()); } @@ -603,7 +605,7 @@ protected void advanceExpunge(VMInstanceVO vm) throws ResourceUnavailableExcepti final Commands cmds = new Commands(Command.OnError.Stop); for (final Command volumeExpungeCommand : volumeExpungeCommands) { - volumeExpungeCommand.setBypassHostMaintenance(expungeCommandCanBypassHostMaintenance(vm)); + volumeExpungeCommand.setBypassHostMaintenance(isValidSystemVMType(vm)); cmds.addCommand(volumeExpungeCommand); } @@ -689,7 +691,7 @@ private void addAllExpungeCommandsFromList(List cmdList, Commands cmds, return; } for (final Command command : cmdList) { - command.setBypassHostMaintenance(expungeCommandCanBypassHostMaintenance(vm)); + command.setBypassHostMaintenance(isValidSystemVMType(vm)); if (s_logger.isTraceEnabled()) { s_logger.trace(String.format("Adding expunge command [%s] for VM [%s]", command.toString(), vm.toString())); } @@ -1191,8 +1193,23 @@ public void orchestrateStart(final String vmUuid, final Map sshAccessDetails = _networkMgr.getSystemVMAccessDetails(vm); + final Map ipAddressDetails = new HashMap<>(sshAccessDetails); + ipAddressDetails.remove(NetworkElementCommand.ROUTER_NAME); + + StartCommand command = new StartCommand(vmTO, dest.getHost(), getExecuteInSequence(vm.getHypervisorType())); + if (isValidSystemVMType(vm)) { + final Certificate certificate = caManager.issueCertificate(null, Arrays.asList(vmProfile.getHostName(), vmProfile.getInstanceName()), + new ArrayList<>(ipAddressDetails.values()), CAManager.CertValidityPeriod.value(), null); + try { + command.setCertificate(CertUtils.x509CertificateToPem(certificate.getClientCertificate())); + command.setCaCertificates(CertUtils.x509CertificatesToPem(certificate.getCaCertificates())); + command.setPrivateKey(CertUtils.privateKeyToPem(certificate.getPrivateKey())); + } catch (IOException e) { + throw new CloudRuntimeException("Failed to generate/setup certificates for system VM"); + } + } + cmds.addCommand(command); vmGuru.finalizeDeployment(cmds, vmProfile, dest, ctx); @@ -1243,6 +1260,24 @@ public void orchestrateStart(final String vmUuid, final Map 0; retries--) { + try { + final Certificate certificate = caManager.issueCertificate(null, Arrays.asList(vm.getHostName(), vm.getInstanceName()), + new ArrayList<>(ipAddressDetails.values()), CAManager.CertValidityPeriod.value(), null); + final boolean result = caManager.deployCertificate(vmHost, certificate, false, sshAccessDetails); + if (!result) { + s_logger.error("Failed to setup certificate for system vm: " + vm.getInstanceName()); + } + return; + } catch (final Exception e) { + s_logger.error("Retrying after catching exception while trying to secure agent for systemvm id=" + vm.getId(), e); + } + } + throw new CloudRuntimeException("Failed to setup and secure agent for systemvm id=" + vm.getId()); + } return; } else { if (s_logger.isDebugEnabled()) { diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java index b2d64393c111..38b505f561ac 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java @@ -47,7 +47,6 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR ExecutionResult result; try { result = getSystemVmVersionAndChecksum(serverResource, controlIp); - FileUtil.scpPatchFiles(controlIp, "/home/cloud", sshPort, pemFile, serverResource.newSrcFiles, LibvirtComputingResource.BASEPATH); } catch (CloudRuntimeException e) { return new PatchSystemVmAnswer(cmd, e.getMessage()); } @@ -59,7 +58,7 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR } String scriptChecksum = lines[1].trim(); - String checksum = serverResource.calculateCurrentChecksum(sysVMName).trim(); + String checksum = serverResource.calculateCurrentChecksum(sysVMName, "vms/cloud-scripts.tgz").trim(); if (!StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum)) { if (!cmd.isForced()) { @@ -71,6 +70,7 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR Pair patchResult = null; try { + FileUtil.scpPatchFiles(controlIp, "/home/cloud", sshPort, pemFile, serverResource.newSrcFiles, LibvirtComputingResource.BASEPATH); patchResult = SshHelper.sshExecute(controlIp, sshPort, "root", pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 600000); } catch (Exception e) { @@ -78,7 +78,17 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR } if (patchResult.first()) { - return new PatchSystemVmAnswer(cmd, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], lines[1]); + String scriptVersion = lines[1]; + if (patchResult.second() != null) { + String res = patchResult.second().replace("\n", " "); + String[] output = res.split(":"); + if (output.length != 2) { + s_logger.warn("Failed to get the latest script version"); + } else { + scriptVersion = output[1].split(" ")[0]; + } + } + return new PatchSystemVmAnswer(cmd, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], scriptVersion); } return new PatchSystemVmAnswer(cmd, patchResult.second()); } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java index 2ac8bf798482..b83514fd8f9c 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java @@ -121,6 +121,16 @@ public Answer execute(final StartCommand command, final LibvirtComputingResource try { File pemFile = new File(LibvirtComputingResource.SSHPRVKEYPATH); FileUtil.scpPatchFiles(controlIp, "/home/cloud", Integer.parseInt(LibvirtComputingResource.DEFAULTDOMRSSHPORT), pemFile, LibvirtComputingResource.newSrcFiles, LibvirtComputingResource.BASEPATH); +// if (Arrays.asList((new VirtualMachine.Type[]{VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm})).contains(vmSpec.getType())) { +//// for (String certFile : LibvirtComputingResource.certificateFiles) { +//// libvirtComputingResource.createFileInVR(controlIp, "/usr/local/cloud/systemvm/conf/", certFile, command.getCertificate()); +//// } +// if (VirtualMachine.Type.ConsoleProxy == vmSpec.getType() || VirtualMachine.Type.SecondaryStorageVm == vmSpec.getType()) { +// libvirtComputingResource. +// libvirtComputingResource.createFileInVR(controlIp, "/home/cloud", KeyStoreUtils.CACERT_FILENAME, command.getCaCertificates()); +// libvirtComputingResource.createFileInVR(controlIp, "/home/cloud", KeyStoreUtils.PKEY_FILENAME, command.getPrivateKey()); +// } +// } // TODO: May want to remove this when cert patching logic is moved Thread.sleep(10000); } catch (Exception e) { @@ -158,6 +168,28 @@ public Answer execute(final StartCommand command, final LibvirtComputingResource } } +// /** +// * Create temporary file and return its path +// */ +// private String createTemporaryFile(String certificateName, String certificate, String filePrefix) { +// String tempCerFilePath = String.format("/tmp/%s-%s", +// filePrefix, certificateName); +// s_logger.debug("Creating temporary certificate file into: " + tempCerFilePath); +// int result = Script.runSimpleBashScriptForExitValue(String.format("echo '%s' > %s", certificate, tempCerFilePath)); +// if (result != 0) { +// throw new CloudRuntimeException("Could not create the certificate file on path: " + tempCerFilePath); +// } +// return tempCerFilePath; +// } +// +// /** +// * Remove temporary file +// */ +// private void cleanupTemporaryFile(String temporaryFile) { +// s_logger.debug("Cleaning up temporary certificate file"); +// Script.runSimpleBashScript("rm -f " + temporaryFile); +// } + private void performAgentStartHook(String vmName, LibvirtComputingResource libvirtComputingResource) { try { LibvirtKvmAgentHook onStartHook = libvirtComputingResource.getStartHook(); diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index f759d118db17..f390c3d9300e 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -655,7 +655,7 @@ private ExecutionResult getSystemVmVersionAndChecksum(String controlIp) { } private Answer execute(PatchSystemVmCommand cmd) { - String controlIp = getRouterSshControlIp(cmd); + String controlIp = cmd.getAccessDetail((NetworkElementCommand.ROUTER_IP)); String sysVMName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); String homeDir = System.getProperty("user.home"); File pemFile = new File(homeDir + "/.ssh/id_rsa"); @@ -674,7 +674,7 @@ private Answer execute(PatchSystemVmCommand cmd) { } String scriptChecksum = lines[1].trim(); - String checksum = calculateCurrentChecksum(sysVMName).trim(); + String checksum = calculateCurrentChecksum(sysVMName, "vms/cloud-scripts.tgz").trim(); if (!org.apache.commons.lang3.StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum)) { if (!cmd.isForced()) { @@ -693,7 +693,17 @@ private Answer execute(PatchSystemVmCommand cmd) { } if (patchResult.first()) { - return new PatchSystemVmAnswer(cmd, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], lines[1]); + String scriptVersion = lines[1]; + if (patchResult.second() != null) { + String res = patchResult.second().replace("\n", " "); + String[] output = res.split(":"); + if (output.length != 2) { + s_logger.warn("Failed to get the latest script version"); + } else { + scriptVersion = output[1].split(" ")[0]; + } + } + return new PatchSystemVmAnswer(cmd, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], scriptVersion); } return new PatchSystemVmAnswer(cmd, patchResult.second()); diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java index 39dd0e59fedd..010fad4c1e93 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java @@ -1121,9 +1121,6 @@ public VBD createPatchVbd(final Connection conn, final String vmName, final VM v _host.setSystemvmisouuid(vdi.getRecord(conn).uuid); } } - if (_host.getSystemvmisouuid() == null) { - throw new CloudRuntimeException("can not find systemvmiso"); - } } final VBD.Record cdromVBDR = new VBD.Record(); @@ -1133,10 +1130,8 @@ public VBD createPatchVbd(final Connection conn, final String vmName, final VM v cdromVBDR.userdevice = "3"; cdromVBDR.mode = Types.VbdMode.RO; cdromVBDR.type = Types.VbdType.CD; - final VBD cdromVBD = VBD.create(conn, cdromVBDR); - cdromVBD.insert(conn, VDI.getByUuid(conn, _host.getSystemvmisouuid())); - return cdromVBD; + return VBD.create(conn, cdromVBDR); } protected boolean createSecondaryStorageFolder(final Connection conn, final String remoteMountPath, final String newFolder) { @@ -1425,7 +1420,7 @@ public VM createVmFromTemplate(final Connection conn, final VirtualMachineTO vmS final DiskTO[] disks = vmSpec.getDisks(); for (final DiskTO disk : disks) { if (disk.getType() == Volume.Type.ISO) { - final TemplateObjectTO iso = (TemplateObjectTO)disk.getData(); + final TemplateObjectTO iso = (TemplateObjectTO) disk.getData(); final String osType = iso.getGuestOsType(); if (osType != null) { final String isoGuestOsName = getGuestOsType(vmSpec.getPlatformEmulator()); diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixNetworkElementCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixNetworkElementCommandWrapper.java index da2bf1e126e2..3e763155fbdc 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixNetworkElementCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixNetworkElementCommandWrapper.java @@ -25,10 +25,11 @@ import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; import com.cloud.resource.CommandWrapper; import com.cloud.resource.ResourceWrapper; +import org.apache.log4j.Logger; @ResourceWrapper(handles = NetworkElementCommand.class) public final class CitrixNetworkElementCommandWrapper extends CommandWrapper { - + private static final Logger s_logger = Logger.getLogger(CitrixNetworkElementCommandWrapper.class); @Override public Answer execute(final NetworkElementCommand command, final CitrixResourceBase citrixResourceBase) { final VirtualRoutingResource routingResource = citrixResourceBase.getVirtualRoutingResource(); diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java index 883c9378aa0c..e806e7e27d55 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java @@ -47,7 +47,6 @@ public Answer execute(PatchSystemVmCommand command, CitrixResourceBase serverRes ExecutionResult result; try { result = getSystemVmVersionAndChecksum(serverResource, controlIp); - serverResource.copyPatchFilesToVR(controlIp, "/home/cloud"); } catch (CloudRuntimeException e) { return new PatchSystemVmAnswer(command, e.getMessage()); } @@ -59,8 +58,7 @@ public Answer execute(PatchSystemVmCommand command, CitrixResourceBase serverRes } String scriptChecksum = lines[1].trim(); - String checksum = serverResource.calculateCurrentChecksum(sysVMName).trim(); - + String checksum = serverResource.calculateCurrentChecksum(sysVMName, "vms/cloud-scripts.tgz").trim(); if (!StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum)) { if (!command.isForced()) { String msg = String.format("No change in the scripts checksum, not patching systemVM %s", sysVMName); @@ -70,14 +68,23 @@ public Answer execute(PatchSystemVmCommand command, CitrixResourceBase serverRes } String patchResult = null; try { + serverResource.copyPatchFilesToVR(controlIp, "/home/cloud"); patchResult = serverResource.callHostPlugin(conn, "vmops", "runPatchScriptInDomr", "domrip", controlIp); } catch (Exception e) { return new PatchSystemVmAnswer(command, e.getMessage()); } - if (patchResult.startsWith("succ#")) { - return new PatchSystemVmAnswer(command, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], lines[1]); + String scriptVersion = lines[1]; + String res = patchResult.replace("\n", " "); + String[] output = res.split(":"); + if (output.length != 2) { + s_logger.warn("Failed to get the latest script version"); + } else { + scriptVersion = output[1].split(" ")[0]; + } + + return new PatchSystemVmAnswer(command, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], scriptVersion); } return new PatchSystemVmAnswer(command, patchResult.substring(5)); diff --git a/scripts/util/keystore-cert-import b/scripts/util/keystore-cert-import index 7c750a412eb8..cbfd0b40e855 100755 --- a/scripts/util/keystore-cert-import +++ b/scripts/util/keystore-cert-import @@ -18,15 +18,14 @@ PROPS_FILE="$1" KS_PASS="$2" -KS_VALIDITY="$3" -KS_FILE="$4" -MODE="$5" -CERT_FILE="$6" -CERT=$(echo "$7" | tr '^' '\n' | tr '~' ' ') -CACERT_FILE="$8" -CACERT=$(echo "$9" | tr '^' '\n' | tr '~' ' ') -PRIVKEY_FILE="${10}" -PRIVKEY=$(echo "${11}" | tr '^' '\n' | tr '~' ' ') +KS_FILE="$3" +MODE="$4" +CERT_FILE="$5" +CERT=$(echo "$6" | tr '^' '\n' | tr '~' ' ') +CACERT_FILE="$7" +CACERT=$(echo "$8" | tr '^' '\n' | tr '~' ' ') +PRIVKEY_FILE="$9" +PRIVKEY=$(echo "${10}" | tr '^' '\n' | tr '~' ' ') ALIAS="cloud" SYSTEM_FILE="/var/cache/cloud/cmdline" @@ -44,13 +43,14 @@ if [ ! -f "$LIBVIRTD_FILE" ]; then fi fi - if [ -f "$KS_FILE" ]; then - keytool -delete -noprompt -alias "$ALIAS" -keystore "$KS_FILE" -storepass "$KS_PASS" > /dev/null 2>&1 || true - fi - - CN=$(hostname --fqdn) - keytool -genkey -storepass "$KS_PASS" -keypass "$KS_PASS" -alias "$ALIAS" -keyalg RSA -validity "$KS_VALIDITY" -dname cn="$CN",ou="cloudstack",o="cloudstack",c="cloudstack" -keystore "$KS_FILE" > /dev/null 2>&1 +# if [ -f "$KS_FILE" ]; then +# keytool -delete -noprompt -alias "$ALIAS" -keystore "$KS_FILE" -storepass "$KS_PASS" > /dev/null 2>&1 || true +# fi +# +# CN=$(hostname --fqdn) +# keytool -genkey -storepass "$KS_PASS" -keypass "$KS_PASS" -alias "$ALIAS" -keyalg RSA -validity "$KS_VALIDITY" -dname cn="$CN",ou="cloudstack",o="cloudstack",c="cloudstack" -keystore "$KS_FILE" > /dev/null 2>&1 fi + # Find keystore password KS_PASS=$(sed -n '/keystore.passphrase/p' "$PROPS_FILE" 2>/dev/null | sed 's/keystore.passphrase=//g' 2>/dev/null) @@ -62,11 +62,17 @@ fi # Import certificate if [ ! -z "${CERT// }" ]; then echo "$CERT" > "$CERT_FILE" +elif [ ! -f "$CERT_FILE" ]; then + echo "Cannot find certificate file: $CERT_FILE, exiting" + exit fi # Import ca certs if [ ! -z "${CACERT// }" ]; then echo "$CACERT" > "$CACERT_FILE" +elif [ ! -f "$CACERT_FILE" ]; then + echo "Cannot find ca certificate file: $CACERT_FILE, exiting!" + exit fi # Import cacerts into the keystore @@ -77,9 +83,16 @@ for caChain in $(ls cloudca.*); do done rm -f cloudca.* +# Stop cloud service in systemvm +if [ "$MODE" == "ssh" ] && [ -f $SYSTEM_FILE ]; then + systemctl stop cloud > /dev/null 2>&1 +fi + # Import private key if available if [ ! -z "${PRIVKEY// }" ]; then echo "$PRIVKEY" > "$PRIVKEY_FILE" +fi +if [ -f "$PRIVKEY_FILE" ]; then # Re-initialize keystore when private key is provided keytool -delete -noprompt -alias "$ALIAS" -keystore "$KS_FILE" -storepass "$KS_PASS" 2>/dev/null || true openssl pkcs12 -export -name "$ALIAS" -in "$CERT_FILE" -inkey "$PRIVKEY_FILE" -out "$KS_FILE.p12" -password pass:"$KS_PASS" > /dev/null 2>&1 @@ -115,6 +128,10 @@ if [ -f "$SYSTEM_FILE" ]; then chmod 644 /usr/local/share/ca-certificates/cloudstack/ca.crt update-ca-certificates > /dev/null 2>&1 || true + # Ensure cloud service is running in systemvm + if [ "$MODE" == "ssh" ]; then + systemctl start cloud > /dev/null 2>&1 + fi fi # Fix file permission diff --git a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 40c6363ce169..15ab2cc44907 100644 --- a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -29,6 +29,7 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.utils.PasswordGenerator; import org.apache.cloudstack.agent.lb.IndirectAgentLB; import org.apache.cloudstack.ca.CAManager; import org.apache.cloudstack.context.CallContext; @@ -1283,8 +1284,8 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl if (dc.getDns2() != null) { buf.append(" dns2=").append(dc.getDns2()); } - - VirtualMachineGuru.appendCertificateDetails(buf, certificate); + buf.append(" keystore_password=").append(VirtualMachineGuru.getEncodedString(PasswordGenerator.generateRandomPassword(16))); +// VirtualMachineGuru.appendCertificateDetails(buf, certificate); String bootArgs = buf.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug("Boot Args for " + profile + ": " + bootArgs); diff --git a/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java b/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java index a67925bbef45..a33f61b98b74 100644 --- a/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java +++ b/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java @@ -186,14 +186,13 @@ private void setupAgentSecurity(final Connection sshConnection, final String age final SetupCertificateCommand certificateCommand = new SetupCertificateCommand(certificate); final SSHCmdHelper.SSHCmdResult setupCertResult = SSHCmdHelper.sshExecuteCmdWithResult(sshConnection, String.format("sudo /usr/share/cloudstack-common/scripts/util/%s " + - "/etc/cloudstack/agent/agent.properties %s %s " + - " /etc/cloudstack/agent/%s %s " + + "/etc/cloudstack/agent/agent.properties %s " + + "/etc/cloudstack/agent/%s %s " + "/etc/cloudstack/agent/%s \"%s\" " + "/etc/cloudstack/agent/%s \"%s\" " + "/etc/cloudstack/agent/%s \"%s\"", KeyStoreUtils.KS_IMPORT_SCRIPT, keystorePassword, - validityPeriod, KeyStoreUtils.KS_FILENAME, KeyStoreUtils.SSH_MODE, KeyStoreUtils.CERT_FILENAME, @@ -257,7 +256,6 @@ private void setupAgentSecurity(final Connection sshConnection, final String age } } - s_logger.info("PEARL - agent IP: "+ agentIp); sshConnection = new Connection(agentIp, 22); sshConnection.connect(null, 60000, 60000); diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index 03a806500de2..8a2dc90b8ccb 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -4717,6 +4717,7 @@ private boolean updateRouterDetails(Long routerId, String scriptVersion, String if (router == null) { throw new CloudRuntimeException(String.format("Failed to find router with id: %s", routerId)); } + router.setTemplateVersion(templateVersion); router.setScriptsVersion(scriptVersion); return routerDao.update(routerId, router); diff --git a/server/src/main/java/org/apache/cloudstack/ca/CAManagerImpl.java b/server/src/main/java/org/apache/cloudstack/ca/CAManagerImpl.java index 1e5d8127053b..5f4a16e1fe57 100644 --- a/server/src/main/java/org/apache/cloudstack/ca/CAManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/ca/CAManagerImpl.java @@ -39,6 +39,7 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; +import com.google.common.base.Strings; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.command.admin.ca.IssueCertificateCmd; @@ -184,11 +185,14 @@ public boolean provisionCertificate(final Host host, final Boolean reconnect, fi } CallContext.current().setEventDetails("host id: " + host.getId()); CallContext.current().putContextParameter(Host.class, host.getUuid()); - final String csr; + String csr = null; + try { - csr = generateKeyStoreAndCsr(host, null); - if (StringUtils.isEmpty(csr)) { - return false; + if (host.getType() != Host.Type.ConsoleProxy && host.getType() != Host.Type.SecondaryStorageVM) { + csr = generateKeyStoreAndCsr(host, null); + if (Strings.isNullOrEmpty(csr)) { + return false; + } } final Certificate certificate = issueCertificate(csr, Arrays.asList(host.getName(), host.getPrivateIpAddress()), Arrays.asList(host.getPrivateIpAddress(), host.getPublicIpAddress(), host.getStorageIpAddress()), CAManager.CertValidityPeriod.value(), caProvider); return deployCertificate(host, certificate, reconnect, null); @@ -209,6 +213,11 @@ public String generateKeyStoreAndCsr(final Host host, final Map return answer.getCsr(); } + private boolean isValidSystemVMType(Host.Type type) { + return Host.Type.SecondaryStorageVM.equals(type) || + Host.Type.ConsoleProxy.equals(type); + } + @Override public boolean deployCertificate(final Host host, final Certificate certificate, final Boolean reconnect, final Map sshAccessDetails) throws AgentUnavailableException, OperationTimedoutException { diff --git a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java index 8f6f12b07649..6c9ce8570551 100644 --- a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java +++ b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java @@ -32,7 +32,6 @@ import java.util.concurrent.Executor; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.ArrayUtils; import org.apache.log4j.xml.DOMConfigurator; import org.eclipse.jetty.websocket.api.Session; @@ -110,9 +109,10 @@ private static void configLog4j() { private static void configProxy(Properties conf) { s_logger.info("Configure console proxy..."); for (Object key : conf.keySet()) { - if (!ArrayUtils.contains(skipProperties, key)) { - s_logger.info("Property " + (String)key + ": " + conf.getProperty((String)key)); - } + s_logger.info("Property " + (String)key + ": " + conf.getProperty((String)key)); +// if (!ArrayUtils.contains(skipProperties, key)) { +// s_logger.info("Property " + (String)key + ": " + conf.getProperty((String)key)); +// } } String s = conf.getProperty("consoleproxy.httpListenPort"); @@ -251,9 +251,10 @@ public static void startWithContext(Properties conf, Object context, byte[] ksBi if (conf != null) { for (Object key : conf.keySet()) { - if (!ArrayUtils.contains(skipProperties, key)) { - s_logger.info("Context property " + (String) key + ": " + conf.getProperty((String) key)); - } +// if (!ArrayUtils.contains(skipProperties, key)) { + s_logger.info("Context property " + (String) key + ": " + conf.getProperty((String) key)); +// s_logger.info("Context property " + (String) key + ": " + conf.getProperty((String) key)); +// } } } diff --git a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java index 15a12723f2e8..d56d51454b68 100644 --- a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java +++ b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java @@ -30,6 +30,7 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.utils.PasswordGenerator; import org.apache.cloudstack.agent.lb.IndirectAgentLB; import org.apache.cloudstack.ca.CAManager; import org.apache.cloudstack.context.CallContext; @@ -1166,8 +1167,8 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl } String nfsVersion = imageStoreDetailsUtil != null ? imageStoreDetailsUtil.getNfsVersion(secStore.getId()) : null; buf.append(" nfsVersion=").append(nfsVersion); - - VirtualMachineGuru.appendCertificateDetails(buf, certificate); + buf.append(" keystore_password=").append(VirtualMachineGuru.getEncodedString(PasswordGenerator.generateRandomPassword(16))); + //VirtualMachineGuru.appendCertificateDetails(buf, certificate); String bootArgs = buf.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug(String.format("Boot args for machine profile [%s]: [%s].", profile.toString(), bootArgs)); diff --git a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config index 15da63e93c6b..69044a3245b2 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config +++ b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config @@ -96,6 +96,9 @@ patch() { cleanup() { rm -rf /home/cloud/agent.zip mv /home/cloud/cloud-scripts.tgz /usr/share/cloud/cloud-scripts.tgz + if [ -f /home/cloud/cloud.crt ]; then + mv /home/cloud/cloud.crt /home/cloud/cloud.ca.crt /home/cloud/cloud.key /usr/local/cloud/systemvm/conf/ + fi } start() { diff --git a/systemvm/debian/opt/cloud/bin/setup/common.sh b/systemvm/debian/opt/cloud/bin/setup/common.sh index 3f4817a07795..82edc511e7fa 100755 --- a/systemvm/debian/opt/cloud/bin/setup/common.sh +++ b/systemvm/debian/opt/cloud/bin/setup/common.sh @@ -594,14 +594,10 @@ routing_svcs() { } setup_certificates() { - certificate=$(echo "$CERTIFICATE" | base64 -d) - cacertificate=$(echo "$CACERTIFICATE" | base64 -d) - privatekey=$(echo "$PRIVATEKEY" | base64 -d) kspass=$(echo "$KEYSTORE_PSSWD"| base64 -d) - ksvalidity="$KS_VALIDITY" - timeout 600 /opt/cloud/bin/keystore-cert-import /usr/local/cloud/systemvm/conf/agent.properties $kspass $ksvalidity \ - /usr/local/cloud/systemvm/conf/cloud.jks ssh /usr/local/cloud/systemvm/conf/cloud.crt \ - $certificate /usr/local/cloud/systemvm/conf/cloud.ca.crt $cacertificate /usr/local/cloud/systemvm/conf/cloud.key $privatekey + timeout 600 /opt/cloud/bin/keystore-cert-import /usr/local/cloud/systemvm/conf/agent.properties "$kspass" \ + /usr/local/cloud/systemvm/conf/cloud.jks ssh /usr/local/cloud/systemvm/conf/cloud.crt "" \ + /usr/local/cloud/systemvm/conf/cloud.ca.crt "" /usr/local/cloud/systemvm/conf/cloud.key "" } parse_cmd_line() { diff --git a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh index f8fcb51d94cb..82e020f3b353 100755 --- a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh +++ b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh @@ -37,10 +37,13 @@ setup_console_proxy() { enable_irqbalance 0 rm -f /etc/logrotate.d/cloud - setup_certificates - if [ $? -gt 0 ]; then - log_it "Failed to setup CA Certificate for $TYPE" - fi +# if [ -f /home/cloud/cloud.crt ]; then +# mv /home/cloud/cloud.crt /home/cloud/cloud.ca.crt /home/cloud/cloud.key /usr/local/cloud/systemvm/conf/ +# fi +# setup_certificates +# if [ $? -gt 0 ]; then +# log_it "Failed to setup CA Certificate for $TYPE" +# fi } setup_console_proxy diff --git a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh index 041853287a34..115521d17b2a 100755 --- a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh +++ b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh @@ -66,10 +66,10 @@ CORS setup_ntp rm -f /etc/logrotate.d/cloud - setup_certificates - if [ $? -gt 0 ]; then - log_it "Failed to setup CA Certificate for $TYPE" - fi +# setup_certificates +# if [ $? -gt 0 ]; then +# log_it "Failed to setup CA Certificate for $TYPE" +# fi } setup_secstorage diff --git a/systemvm/patch-sysvms.sh b/systemvm/patch-sysvms.sh index ee3c78a6270a..4edb780310ab 100644 --- a/systemvm/patch-sysvms.sh +++ b/systemvm/patch-sysvms.sh @@ -25,35 +25,38 @@ md5file=/var/cache/cloud/cloud-scripts-signature svcfile=/var/cache/cloud/enabled_svcs TYPE=$(grep -Po 'type=\K[a-zA-Z]*' $CMDLINE) patchfailed=0 - +backuprestored=0 backup_old_package() { mkdir -p $backupfolder - echo "Backing up keystore file and certificates" > $logfile + echo "Backing up keystore file and certificates" > $logfile 2>&1 mkdir -p $backupfolder/conf cp -r /usr/local/cloud/systemvm/conf/* $backupfolder/conf - echo "Backing up agent package" >> $logfile - zip -r $backupfolder/agent.zip /usr/local/cloud/systemvm/* >> $logfile 2>&1 + echo "Backing up agent package" >> $logfile 2>&1 + cd /usr/local/cloud/systemvm/ + zip -r $backupfolder/agent.zip * >> $logfile 2>&1 2>&1 + cd - cp $md5file $backupfolder - echo "Backing up cloud-scripts file" >> $logfile + echo "Backing up cloud-scripts file" >> $logfile 2>&1 tar -zcvf $backupfolder/cloud-scripts.tgz /etc/ /var/ /opt/ /root/ >> $logfile 2>&1 } restore_backup() { - echo "Restoring cloud scripts" >> $logfile + echo "Restoring cloud scripts" >> $logfile 2>&1 tar -xvf $backupfolder/cloud-scripts.tar -C / >> $logfile 2>&1 - echo "Restoring agent package" >> $logfile + echo "Restoring agent package" >> $logfile 2>&1 unzip $backupfolder/agent.zip -d /usr/local/cloud/systemvm/ >> $logfile 2>&1 - echo "Restore keystore file and certificates" + echo "Restore keystore file and certificates" >> $logfile 2>&1 mkdir -p "/usr/local/cloud/systemvm/conf/" cp -r $backupfolder/conf/* /usr/local/cloud/systemvm/conf/ + backuprestored=1 restart_services cp $backupfolder/cloud-scripts-signature $md5file } update_checksum() { newmd5=$(md5sum $1 | awk '{print $1}') - echo "checksum: " ${newmd5} >> $logfile + echo "checksum: " ${newmd5} >> $logfile 2>&1 echo ${newmd5} > ${md5file} } @@ -61,20 +64,24 @@ restart_services() { systemctl daemon-reload while IFS= read -r line do - echo "$line" for svc in ${line}; do - systemctl restart "$svc" - sleep 5 systemctl is-active --quiet "$svc" - if [ $? -gt 0 ]; then - echo "Failed to start "$svc" service. Patch Failed. Retrying again" >> $logfile - restore_backup - patchfailed=1 - break + if [ $? -eq 0 ]; then + systemctl restart "$svc" + sleep 5 + systemctl is-active --quiet "$svc" + if [ $? -gt 0 ]; then + echo "Failed to start "$svc" service. Patch Failed. Retrying again" >> $logfile 2>&1 + if [ $backuprestored == 0 ]; then + restore_backup + fi + patchfailed=1 + break + fi fi done if [ $patchfailed == 1 ]; then - break + return fi done < "$svcfile" } @@ -91,12 +98,12 @@ patch_systemvm() { echo "All" | unzip $newpath/agent.zip -d /usr/local/cloud/systemvm >> $logfile 2>&1 find /usr/local/cloud/systemvm/ -name \*.sh | xargs chmod 555 - echo "Extracting cloud scripts" >> $logfile + echo "Extracting cloud scripts" >> $logfile 2>&1 tar -xvf $newpath/cloud-scripts.tgz -C / >> $logfile 2>&1 if [ -f $backupfolder/conf/cloud.jks ]; then cp -r $backupfolder/conf/* /usr/local/cloud/systemvm/conf/ - echo "Restored keystore file and certs using backup" >> $logfile + echo "Restored keystore file and certs using backup" >> $logfile 2>&1 fi update_checksum $newpath/cloud-scripts.tgz @@ -111,4 +118,8 @@ backup_old_package patch_systemvm cleanup_systemVM +if [ $patchfailed == 0 ]; then + echo "version:$(cat ${md5file}) " +fi + exit $patchfailed diff --git a/utils/src/main/java/org/apache/cloudstack/utils/security/KeyStoreUtils.java b/utils/src/main/java/org/apache/cloudstack/utils/security/KeyStoreUtils.java index c6f8d21918c4..e78d14adbb2d 100644 --- a/utils/src/main/java/org/apache/cloudstack/utils/security/KeyStoreUtils.java +++ b/utils/src/main/java/org/apache/cloudstack/utils/security/KeyStoreUtils.java @@ -26,6 +26,7 @@ public class KeyStoreUtils { public static final String KS_SETUP_SCRIPT = "keystore-setup"; public static final String KS_IMPORT_SCRIPT = "keystore-cert-import"; + public static final String KS_SYSTEMVM_IMPORT_SCRIPT = "keystore-cert-import-sysvm"; public static final String AGENT_PROPSFILE = "agent.properties"; public static final String KS_PASSPHRASE_PROPERTY = "keystore.passphrase"; From c7e79ec7f3fe96ff9563a57dcd49885e5907be46 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Fri, 7 Jan 2022 17:36:44 +0530 Subject: [PATCH 13/68] remove commented code + change core user to cloud for cks nodes --- debian/rules | 1 - engine/schema/pom.xml | 2 + packaging/centos7/cloud.spec | 3 - packaging/centos8/cloud.spec | 3 - packaging/suse15/cloud.spec | 3 - .../wrapper/LibvirtStartCommandWrapper.java | 10 ---- .../vmware/resource/VmwareResource.java | 21 +++---- .../KubernetesClusterActionWorker.java | 2 +- ...esClusterResourceModifierActionWorker.java | 2 +- .../resources/conf/k8s-control-node-add.yml | 10 ++-- .../main/resources/conf/k8s-control-node.yml | 10 ++-- .../src/main/resources/conf/k8s-node.yml | 10 ++-- scripts/vm/hypervisor/xenserver/xcposs/patch | 1 - .../vm/hypervisor/xenserver/xcpserver/patch | 1 - .../vm/hypervisor/xenserver/xenserver56/patch | 1 - .../hypervisor/xenserver/xenserver56fp1/patch | 1 - .../vm/hypervisor/xenserver/xenserver60/patch | 1 - .../vm/hypervisor/xenserver/xenserver62/patch | 1 - .../vm/hypervisor/xenserver/xenserver65/patch | 1 - .../debian/opt/cloud/bin/setup/cksnode.sh | 6 +- .../opt/cloud/bin/setup/cloud-early-config | 56 ++++++++++--------- systemvm/patch-sysvms.sh | 34 ++++++----- tools/appliance/build.sh | 4 +- .../scripts/configure_systemvm_services.sh | 8 ++- .../appliance/systemvmtemplate/template.json | 4 +- ui/public/locales/en.json | 2 +- 26 files changed, 94 insertions(+), 104 deletions(-) diff --git a/debian/rules b/debian/rules index 1e7f119f47e9..e216fc77a7e0 100755 --- a/debian/rules +++ b/debian/rules @@ -128,7 +128,6 @@ override_dh_auto_install: install -D client/target/utilities/bin/cloud-setup-management $(DESTDIR)/usr/bin/cloudstack-setup-management install -D client/target/utilities/bin/cloud-setup-encryption $(DESTDIR)/usr/bin/cloudstack-setup-encryption install -D client/target/utilities/bin/cloud-sysvmadm $(DESTDIR)/usr/bin/cloudstack-sysvmadm - #install -D systemvm/dist/systemvm.iso $(DESTDIR)/usr/share/$(PACKAGE)-common/vms/systemvm.iso install -D systemvm/dist/* $(DESTDIR)/usr/share/$(PACKAGE)-common/vms/ # We need jasypt for cloud-install-sys-tmplt, so this is a nasty hack to get it into the right place install -D agent/target/dependencies/jasypt-1.9.3.jar $(DESTDIR)/usr/share/$(PACKAGE)-common/lib diff --git a/engine/schema/pom.xml b/engine/schema/pom.xml index 165887e19aea..0d0bee1a2af5 100644 --- a/engine/schema/pom.xml +++ b/engine/schema/pom.xml @@ -102,8 +102,10 @@ File file = new File("./engine/schema/dist/systemvm-templates/md5sum.txt") def lines = file.readLines() for (template in templateList) { + println(template) def data = lines.findAll { it.contains(template) } if (data != null) { + println(template) def hypervisor = template.tokenize('-')[-1] pom.properties["$hypervisor" + ".checksum"] = data[0].tokenize(' ')[0] } diff --git a/packaging/centos7/cloud.spec b/packaging/centos7/cloud.spec index 96915a1660ab..81ee8a77a82f 100644 --- a/packaging/centos7/cloud.spec +++ b/packaging/centos7/cloud.spec @@ -231,7 +231,6 @@ mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms mkdir -p ${RPM_BUILD_ROOT}%{python_sitearch}/ mkdir -p ${RPM_BUILD_ROOT}/usr/bin cp -r scripts/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts -#install -D systemvm/dist/systemvm.iso ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/systemvm.iso install -D systemvm/dist/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/ install python/lib/cloud_utils.py ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py cp -r python/lib/cloudutils ${RPM_BUILD_ROOT}%{python_sitearch}/ @@ -601,8 +600,6 @@ pip3 install --upgrade urllib3 %dir %attr(0755,root,root) %{_datadir}/%{name}-common/vms %attr(0755,root,root) %{_datadir}/%{name}-common/scripts %attr(0755,root,root) /usr/bin/cloudstack-sccs -# TODO: Remove systemvm.iso -#%attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso %attr(0644, root, root) %{_datadir}/%{name}-common/vms/agent.zip %attr(0644, root, root) %{_datadir}/%{name}-common/vms/cloud-scripts.tgz %attr(0644, root, root) %{_datadir}/%{name}-common/vms/patch-sysvms.sh diff --git a/packaging/centos8/cloud.spec b/packaging/centos8/cloud.spec index 35e0e8d53578..1a946ba0dd95 100644 --- a/packaging/centos8/cloud.spec +++ b/packaging/centos8/cloud.spec @@ -224,7 +224,6 @@ mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms mkdir -p ${RPM_BUILD_ROOT}%{python_sitearch}/ mkdir -p ${RPM_BUILD_ROOT}/usr/bin cp -r scripts/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts -#install -D systemvm/dist/systemvm.iso ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/systemvm.iso install -D systemvm/dist/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/ install python/lib/cloud_utils.py ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py cp -r python/lib/cloudutils ${RPM_BUILD_ROOT}%{python_sitearch}/ @@ -589,8 +588,6 @@ pip install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz %dir %attr(0755,root,root) %{_datadir}/%{name}-common/vms %attr(0755,root,root) %{_datadir}/%{name}-common/scripts %attr(0755,root,root) /usr/bin/cloudstack-sccs -# TODO: Remove systemvm.iso -#%attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso %attr(0644, root, root) %{_datadir}/%{name}-common/vms/agent.zip %attr(0644, root, root) %{_datadir}/%{name}-common/vms/cloud-scripts.tgz %attr(0644, root, root) %{_datadir}/%{name}-common/vms/patch-sysvms.sh diff --git a/packaging/suse15/cloud.spec b/packaging/suse15/cloud.spec index bfdfa4826a1a..f355640c8650 100644 --- a/packaging/suse15/cloud.spec +++ b/packaging/suse15/cloud.spec @@ -226,7 +226,6 @@ mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms mkdir -p ${RPM_BUILD_ROOT}%{python_sitearch}/ mkdir -p ${RPM_BUILD_ROOT}/usr/bin cp -r scripts/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts -#install -D systemvm/dist/systemvm.iso ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/systemvm.iso install -D systemvm/dist/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/ install python/lib/cloud_utils.py ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py cp -r python/lib/cloudutils ${RPM_BUILD_ROOT}%{python_sitearch}/ @@ -583,8 +582,6 @@ pip install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz %dir %attr(0755,root,root) %{_datadir}/%{name}-common/vms %attr(0755,root,root) %{_datadir}/%{name}-common/scripts %attr(0755,root,root) /usr/bin/cloudstack-sccs -# TODO: Remove systemvm.iso -#%attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso %attr(0644, root, root) %{_datadir}/%{name}-common/vms/agent.zip %attr(0644, root, root) %{_datadir}/%{name}-common/vms/cloud-scripts.tgz %attr(0644, root, root) %{_datadir}/%{name}-common/vms/patch-sysvms.sh diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java index b83514fd8f9c..1f6a0256cc83 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java @@ -121,16 +121,6 @@ public Answer execute(final StartCommand command, final LibvirtComputingResource try { File pemFile = new File(LibvirtComputingResource.SSHPRVKEYPATH); FileUtil.scpPatchFiles(controlIp, "/home/cloud", Integer.parseInt(LibvirtComputingResource.DEFAULTDOMRSSHPORT), pemFile, LibvirtComputingResource.newSrcFiles, LibvirtComputingResource.BASEPATH); -// if (Arrays.asList((new VirtualMachine.Type[]{VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm})).contains(vmSpec.getType())) { -//// for (String certFile : LibvirtComputingResource.certificateFiles) { -//// libvirtComputingResource.createFileInVR(controlIp, "/usr/local/cloud/systemvm/conf/", certFile, command.getCertificate()); -//// } -// if (VirtualMachine.Type.ConsoleProxy == vmSpec.getType() || VirtualMachine.Type.SecondaryStorageVm == vmSpec.getType()) { -// libvirtComputingResource. -// libvirtComputingResource.createFileInVR(controlIp, "/home/cloud", KeyStoreUtils.CACERT_FILENAME, command.getCaCertificates()); -// libvirtComputingResource.createFileInVR(controlIp, "/home/cloud", KeyStoreUtils.PKEY_FILENAME, command.getPrivateKey()); -// } -// } // TODO: May want to remove this when cert patching logic is moved Thread.sleep(10000); } catch (Exception e) { diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index f390c3d9300e..476734284749 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -692,17 +692,18 @@ private Answer execute(PatchSystemVmCommand cmd) { return new PatchSystemVmAnswer(cmd, e.getMessage()); } - if (patchResult.first()) { - String scriptVersion = lines[1]; - if (patchResult.second() != null) { - String res = patchResult.second().replace("\n", " "); - String[] output = res.split(":"); - if (output.length != 2) { - s_logger.warn("Failed to get the latest script version"); - } else { - scriptVersion = output[1].split(" ")[0]; - } + String scriptVersion = lines[1]; + if (patchResult.second() != null) { + String res = patchResult.second().replace("\n", " "); + String[] output = res.split(":"); + if (output.length != 2) { + s_logger.warn("Failed to get the latest script version"); + } else { + scriptVersion = output[1].split(" ")[0]; } + + } + if (patchResult.first()) { return new PatchSystemVmAnswer(cmd, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], scriptVersion); } return new PatchSystemVmAnswer(cmd, patchResult.second()); diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java index 2399981c5764..eaf00f30a80e 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java @@ -84,7 +84,7 @@ public class KubernetesClusterActionWorker { - public static final String CLUSTER_NODE_VM_USER = "core"; + public static final String CLUSTER_NODE_VM_USER = "cloud"; public static final int CLUSTER_API_PORT = 6443; public static final int CLUSTER_NODES_DEFAULT_START_SSH_PORT = 2222; diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java index 20be84dda448..8a6c81e23ee1 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java @@ -189,7 +189,7 @@ private String getKubernetesNodeConfig(final String joinIp, final boolean ejectI // optional or conditionally applied String dockerConfigString = "write_files:\n" + " - path: /.docker/config.json\n" + - " owner: core:core\n" + + " owner: cloud:cloud\n" + " permissions: '0644'\n" + " content: |\n" + " {\n" + diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml index 87c592426a96..1699ffdcdc51 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml @@ -18,7 +18,7 @@ --- users: - - name: core + - name: cloud sudo: ALL=(ALL) NOPASSWD:ALL shell: /bin/bash ssh_authorized_keys: @@ -31,7 +31,7 @@ write_files: content: | #!/bin/bash -e - if [[ -f "/home/core/success" ]]; then + if [[ -f "/home/cloud/success" ]]; then echo "Already provisioned!" exit 0 fi @@ -192,7 +192,7 @@ write_files: content: | #!/bin/bash -e - if [[ -f "/home/core/success" ]]; then + if [[ -f "/home/cloud/success" ]]; then echo "Already provisioned!" exit 0 fi @@ -210,8 +210,8 @@ write_files: fi kubeadm join {{ k8s_control_node.join_ip }}:6443 --token {{ k8s_control_node.cluster.token }} --control-plane --certificate-key {{ k8s_control_node.cluster.ha.certificate.key }} --discovery-token-unsafe-skip-ca-verification - sudo touch /home/core/success - echo "true" > /home/core/success + sudo touch /home/cloud/success + echo "true" > /home/cloud/success - path: /etc/systemd/system/setup-kube-system.service permissions: '0755' diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml index 55daf7f6b7d3..c93167467b1f 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml @@ -18,7 +18,7 @@ --- users: - - name: core + - name: cloud sudo: ALL=(ALL) NOPASSWD:ALL shell: /bin/bash ssh_authorized_keys: @@ -51,7 +51,7 @@ write_files: content: | #!/bin/bash -e - if [[ -f "/home/core/success" ]]; then + if [[ -f "/home/cloud/success" ]]; then echo "Already provisioned!" exit 0 fi @@ -231,7 +231,7 @@ write_files: content: | #!/bin/bash -e - if [[ -f "/home/core/success" ]]; then + if [[ -f "/home/cloud/success" ]]; then echo "Already provisioned!" exit 0 fi @@ -267,8 +267,8 @@ write_files: /opt/bin/kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=admin || true /opt/bin/kubectl create clusterrolebinding kubernetes-dashboard-ui --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:kubernetes-dashboard || true - sudo touch /home/core/success - echo "true" > /home/core/success + sudo touch /home/cloud/success + echo "true" > /home/cloud/success - path: /etc/systemd/system/setup-kube-system.service permissions: '0755' diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml index ac05c6098f1a..3b22f801f3c3 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml @@ -18,7 +18,7 @@ --- users: - - name: core + - name: cloud sudo: ALL=(ALL) NOPASSWD:ALL shell: /bin/bash ssh_authorized_keys: @@ -31,7 +31,7 @@ write_files: content: | #!/bin/bash -e - if [[ -f "/home/core/success" ]]; then + if [[ -f "/home/cloud/success" ]]; then echo "Already provisioned!" exit 0 fi @@ -192,7 +192,7 @@ write_files: content: | #!/bin/bash -e - if [[ -f "/home/core/success" ]]; then + if [[ -f "/home/cloud/success" ]]; then echo "Already provisioned!" exit 0 fi @@ -210,8 +210,8 @@ write_files: fi kubeadm join {{ k8s_control_node.join_ip }}:6443 --token {{ k8s_control_node.cluster.token }} --discovery-token-unsafe-skip-ca-verification - sudo touch /home/core/success - echo "true" > /home/core/success + sudo touch /home/cloud/success + echo "true" > /home/cloud/success - path: /etc/systemd/system/setup-kube-system.service permissions: '0755' diff --git a/scripts/vm/hypervisor/xenserver/xcposs/patch b/scripts/vm/hypervisor/xenserver/xcposs/patch index 4686e67fe0a7..1edd35ad628a 100644 --- a/scripts/vm/hypervisor/xenserver/xcposs/patch +++ b/scripts/vm/hypervisor/xenserver/xcposs/patch @@ -31,7 +31,6 @@ vmops=..,0755,/usr/lib/xcp/plugins ovsgre=..,0755,/usr/lib/xcp/plugins ovstunnel=..,0755,/usr/lib/xcp/plugins vmopsSnapshot=..,0755,/usr/lib/xcp/plugins -#systemvm.iso=../../../../../vms,0644,/usr/share/xcp/packages/iso/ agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xcpserver/patch b/scripts/vm/hypervisor/xenserver/xcpserver/patch index da6ce60b7f68..8bb1eadd7034 100644 --- a/scripts/vm/hypervisor/xenserver/xcpserver/patch +++ b/scripts/vm/hypervisor/xenserver/xcpserver/patch @@ -31,7 +31,6 @@ NFSSR.py=/opt/xensource/sm vmops=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins -#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xenserver56/patch b/scripts/vm/hypervisor/xenserver/xenserver56/patch index fd844b4b6b05..16b1ce71b922 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver56/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver56/patch @@ -30,7 +30,6 @@ NFSSR.py=/opt/xensource/sm vmops=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins -#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch b/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch index 2a0f4b8aac78..bb09d255601e 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch @@ -30,7 +30,6 @@ NFSSR.py=/opt/xensource/sm vmops=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins -#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xenserver60/patch b/scripts/vm/hypervisor/xenserver/xenserver60/patch index e32be41affa6..2652c30cd05e 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver60/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver60/patch @@ -34,7 +34,6 @@ cloudstack_plugins.conf=..,0644,/etc/xensource cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins -#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xenserver62/patch b/scripts/vm/hypervisor/xenserver/xenserver62/patch index 9bf9b9bdac23..f18a325f05bf 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver62/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver62/patch @@ -35,7 +35,6 @@ cloudstack_plugins.conf=..,0644,/etc/xensource cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins cloud-plugin-storage=..,0755,/etc/xapi.d/plugins -#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xenserver65/patch b/scripts/vm/hypervisor/xenserver/xenserver65/patch index 9bf9b9bdac23..f18a325f05bf 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver65/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver65/patch @@ -35,7 +35,6 @@ cloudstack_plugins.conf=..,0644,/etc/xensource cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins cloud-plugin-storage=..,0755,/etc/xapi.d/plugins -#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/systemvm/debian/opt/cloud/bin/setup/cksnode.sh b/systemvm/debian/opt/cloud/bin/setup/cksnode.sh index 7f580ace9cd4..78ae96631ad9 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cksnode.sh +++ b/systemvm/debian/opt/cloud/bin/setup/cksnode.sh @@ -31,8 +31,8 @@ setup_k8s_node() { systemctl restart ssh # Prevent root login - > /root/.ssh/authorized_keys - passwd -l root +# > /root/.ssh/authorized_keys +# passwd -l root #sed -i 's#root:x:0:0:root:/root:/bin/bash#root:x:0:0:root:/root:/sbin/nologin#' /etc/passwd # Update containerd configuration @@ -66,7 +66,7 @@ setup_k8s_node() { log_it "Starting cloud-init services" systemctl enable --now --no-block containerd - if [ -f /home/core/success ]; then + if [ -f /home/cloud/success ]; then systemctl stop cloud-init cloud-config cloud-final systemctl disable cloud-init cloud-config cloud-final else diff --git a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config index 69044a3245b2..13fa9987a5e7 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config +++ b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config @@ -59,38 +59,42 @@ patch() { return 0 fi + CMDLINE=/var/cache/cloud/cmdline + export TYPE=$(grep -Po 'type=\K[a-zA-Z]*' $CMDLINE) retry=60 local patched=false - while [ $retry -gt 0 ] - do - if [ -f $patchfile ]; then - eval $(validate_checksums $md5file $patchfile) - if [ "$oldmd5" != "$newmd5" ] && [ -f ${patchfile} ] && [ "$newmd5" != "" ] - then - tar xzf $patchfile -C / - ls -lrt /opt/cloud/bin/keystore* - echo ${newmd5} > ${md5file} - log_it "Patched scripts using $patchfile" - touch /var/cache/cloud/patch.required + if [ "$TYPE" != "cksnode" ]; then + while [ $retry -gt 0 ] + do + if [ -f $patchfile ]; then + eval $(validate_checksums $md5file $patchfile) + if [ "$oldmd5" != "$newmd5" ] && [ -f ${patchfile} ] && [ "$newmd5" != "" ] + then + tar xzf $patchfile -C / + ls -lrt /opt/cloud/bin/keystore* + echo ${newmd5} > ${md5file} + log_it "Patched scripts using $patchfile" + touch /var/cache/cloud/patch.required + fi + + if [ -f $privkey ]; then + cp -f $privkey /root/.ssh/ + chmod go-rwx /root/.ssh/authorized_keys + fi + patched=true + break fi - if [ -f $privkey ]; then - cp -f $privkey /root/.ssh/ - chmod go-rwx /root/.ssh/authorized_keys - fi - patched=true - break - fi - - sleep 2 - retry=$(($retry-1)) - log_it "Could not find patch file, retrying" - done + sleep 2 + retry=$(($retry-1)) + log_it "Could not find patch file, retrying" + done - if [ $retry -eq 0 ] && [ "$patched" == "false" ]; then - return 2 + if [ $retry -eq 0 ] && [ "$patched" == "false" ]; then + return 2 + fi + return 0 fi - return 0 } cleanup() { diff --git a/systemvm/patch-sysvms.sh b/systemvm/patch-sysvms.sh index 4edb780310ab..148c8a80b9da 100644 --- a/systemvm/patch-sysvms.sh +++ b/systemvm/patch-sysvms.sh @@ -29,13 +29,17 @@ backuprestored=0 backup_old_package() { mkdir -p $backupfolder - echo "Backing up keystore file and certificates" > $logfile 2>&1 - mkdir -p $backupfolder/conf - cp -r /usr/local/cloud/systemvm/conf/* $backupfolder/conf - echo "Backing up agent package" >> $logfile 2>&1 - cd /usr/local/cloud/systemvm/ - zip -r $backupfolder/agent.zip * >> $logfile 2>&1 2>&1 - cd - + if [ -d /usr/local/cloud/systemvm/conf/ ]; then + echo "Backing up keystore file and certificates" > $logfile 2>&1 + mkdir -p $backupfolder/conf + cp -r /usr/local/cloud/systemvm/conf/* $backupfolder/conf + fi + if [ -d /usr/local/cloud/systemvm/ ]; then + echo "Backing up agent package" >> $logfile 2>&1 + cd /usr/local/cloud/systemvm/ + zip -r $backupfolder/agent.zip * >> $logfile 2>&1 2>&1 + cd - + fi cp $md5file $backupfolder echo "Backing up cloud-scripts file" >> $logfile 2>&1 tar -zcvf $backupfolder/cloud-scripts.tgz /etc/ /var/ /opt/ /root/ >> $logfile 2>&1 @@ -45,10 +49,12 @@ restore_backup() { echo "Restoring cloud scripts" >> $logfile 2>&1 tar -xvf $backupfolder/cloud-scripts.tar -C / >> $logfile 2>&1 echo "Restoring agent package" >> $logfile 2>&1 - unzip $backupfolder/agent.zip -d /usr/local/cloud/systemvm/ >> $logfile 2>&1 - echo "Restore keystore file and certificates" >> $logfile 2>&1 - mkdir -p "/usr/local/cloud/systemvm/conf/" - cp -r $backupfolder/conf/* /usr/local/cloud/systemvm/conf/ + if [ -f $backupfolder/agent.zip ]; then + unzip $backupfolder/agent.zip -d /usr/local/cloud/systemvm/ >> $logfile 2>&1 + echo "Restore keystore file and certificates" >> $logfile 2>&1 + mkdir -p "/usr/local/cloud/systemvm/conf/" + cp -r $backupfolder/conf/* /usr/local/cloud/systemvm/conf/ + fi backuprestored=1 restart_services cp $backupfolder/cloud-scripts-signature $md5file @@ -95,9 +101,11 @@ cleanup_systemVM() { patch_systemvm() { rm -rf /usr/local/cloud/systemvm mkdir -p /usr/local/cloud/systemvm - echo "All" | unzip $newpath/agent.zip -d /usr/local/cloud/systemvm >> $logfile 2>&1 - find /usr/local/cloud/systemvm/ -name \*.sh | xargs chmod 555 + if [ "$TYPE" == "consoleproxy" ] || [ "$TYPE" == "secstorage" ]; then + echo "All" | unzip $newpath/agent.zip -d /usr/local/cloud/systemvm >> $logfile 2>&1 + find /usr/local/cloud/systemvm/ -name \*.sh | xargs chmod 555 + fi echo "Extracting cloud scripts" >> $logfile 2>&1 tar -xvf $newpath/cloud-scripts.tgz -C / >> $logfile 2>&1 diff --git a/tools/appliance/build.sh b/tools/appliance/build.sh index 5a97c9dbf6b6..285d818c0c75 100755 --- a/tools/appliance/build.sh +++ b/tools/appliance/build.sh @@ -348,9 +348,9 @@ function main() { packer_build # process the disk at dist - kvm_export +# kvm_export # ovm_export - xen_server_export +# xen_server_export vmware_export # hyperv_export rm -f "dist/${appliance}" diff --git a/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh b/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh index 4f97b1b5505e..36b324a314f8 100644 --- a/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh +++ b/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh @@ -50,9 +50,11 @@ function configure_cacerts() { CDIR=$(pwd) cd /tmp # Add LetsEncrypt ca-cert - wget https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.der - keytool -trustcacerts -keystore /etc/ssl/certs/java/cacerts -storepass changeit -noprompt -importcert -alias letsencryptauthorityx3cross -file lets-encrypt-x3-cross-signed.der - rm -f lets-encrypt-x3-cross-signed.der + wget https://letsencrypt.org/certs/lets-encrypt-r3.der + wget https://letsencrypt.org/certs/isrgrootx1.der + keytool -trustcacerts -keystore /etc/ssl/certs/java/cacerts -storepass changeit -noprompt -importcert -alias letsencryptauthorityr3 -file lets-encrypt-r3.der + keytool -trustcacerts -keystore /etc/ssl/certs/java/cacerts -storepass changeit -noprompt -importcert -alias letsencryptauthorityx1 -file isrgrootx1.der + rm -f lets-encrypt-r3.der isrgrootx1.der cd $CDIR } diff --git a/tools/appliance/systemvmtemplate/template.json b/tools/appliance/systemvmtemplate/template.json index 46fdbc90a750..31eb2ea5abf1 100644 --- a/tools/appliance/systemvmtemplate/template.json +++ b/tools/appliance/systemvmtemplate/template.json @@ -27,8 +27,8 @@ "format": "qcow2", "headless": true, "http_directory": "http", - "iso_checksum": "sha512:02257c3ec27e45d9f022c181a69b59da67e5c72871cdb4f9a69db323a1fad58093f2e69702d29aa98f5f65e920e0b970d816475a5a936e1f3bf33832257b7e92", - "iso_url": "https://cdimage.debian.org/debian-cd/11.1.0/amd64/iso-cd/debian-11.1.0-amd64-netinst.iso", + "iso_checksum": "sha512:c685b85cf9f248633ba3cd2b9f9e781fa03225587e0c332aef2063f6877a1f0622f56d44cf0690087b0ca36883147ecb5593e3da6f965968402cdbdf12f6dd74", + "iso_url": "https://cdimage.debian.org/debian-cd/11.2.0/amd64/iso-cd/debian-11.2.0-amd64-netinst.iso", "net_device": "virtio-net", "output_directory": "../dist", "qemuargs": [ diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index d81dd7a1e3ec..76e2f35ced56 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -1241,7 +1241,7 @@ "label.keypair": "SSH Key Pair", "label.kubeconfig.cluster": "Kubernetes Cluster Config", "label.kubernetes": "Kubernetes", -"label.kubernetes.access.details": "The kubernetes nodes can be accessed via ssh using:
ssh -i [ssh_key] -p [port_number] core@[public_ip_address]

where,
ssh_key: points to the ssh private key file corresponding to the key that was associated while creating the Kubernetes cluster. If no ssh key was provided during Kubernetes cluster creation, use the ssh private key of the management server.
port_number: can be obtained from the Port Forwarding Tab (Public Port column)", +"label.kubernetes.access.details": "The kubernetes nodes can be accessed via ssh using:
ssh -i [ssh_key] -p [port_number] cloud@[public_ip_address]

where,
ssh_key: points to the ssh private key file corresponding to the key that was associated while creating the Kubernetes cluster. If no ssh key was provided during Kubernetes cluster creation, use the ssh private key of the management server.
port_number: can be obtained from the Port Forwarding Tab (Public Port column)", "label.kubernetes.cluster": "Kubernetes cluster", "label.kubernetes.cluster.create": "Create Kubernetes Cluster", "label.kubernetes.cluster.delete": "Delete Kubernetes Cluster", From e3d0051f8eb2e9c066a8f9a17d9ec889ff0bc6ea Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Fri, 7 Jan 2022 17:57:12 +0530 Subject: [PATCH 14/68] Update ownership of ssh directory --- .../src/main/resources/conf/k8s-control-node-add.yml | 1 + .../src/main/resources/conf/k8s-control-node.yml | 1 + .../kubernetes-service/src/main/resources/conf/k8s-node.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml index 1699ffdcdc51..db295188eba5 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml @@ -241,6 +241,7 @@ write_files: ExecStart=/opt/bin/deploy-kube-system runcmd: + - chown -R cloud:cloud /home/cloud/.ssh - [ systemctl, start, setup-kube-system ] - [ systemctl, start, deploy-kube-system ] diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml index c93167467b1f..730477bd4eef 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml @@ -298,6 +298,7 @@ write_files: ExecStart=/opt/bin/deploy-kube-system runcmd: + - chown -R cloud:cloud /home/cloud/.ssh - [ systemctl, start, setup-kube-system ] - [ systemctl, start, deploy-kube-system ] diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml index 3b22f801f3c3..eea369921ac8 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml @@ -241,5 +241,6 @@ write_files: ExecStart=/opt/bin/deploy-kube-system runcmd: + - chown -R cloud:cloud /home/cloud/.ssh - [ systemctl, start, setup-kube-system ] - [ systemctl, start, deploy-kube-system ] From 84f31acd72d8f6caddaaf15a5a6ffe091604b737 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Mon, 10 Jan 2022 17:26:39 +0530 Subject: [PATCH 15/68] NEED TO DISCUSS - add on the fly template conversion as an ExecStartPre action (systemd) --- debian/control | 2 +- engine/schema/pom.xml | 57 +++---- packaging/centos7/cloud.spec | 1 + packaging/centos8/cloud.spec | 1 + packaging/suse15/cloud.spec | 1 + .../systemd/cloudstack-management.service | 2 + scripts/installer/export-templates.sh | 158 ++++++++++++++++++ scripts/util/keystore-cert-import | 5 +- systemvm/debian/opt/cloud/bin/setup/common.sh | 7 - .../opt/cloud/bin/setup/consoleproxy.sh | 7 - .../debian/opt/cloud/bin/setup/secstorage.sh | 4 - 11 files changed, 194 insertions(+), 51 deletions(-) create mode 100644 scripts/installer/export-templates.sh diff --git a/debian/control b/debian/control index 066994785b38..06edfa3c5cac 100644 --- a/debian/control +++ b/debian/control @@ -15,7 +15,7 @@ Description: A common package which contains files which are shared by several C Package: cloudstack-management Architecture: all -Depends: ${python3:Depends}, openjdk-11-jre-headless | java11-runtime-headless | java11-runtime | openjdk-11-jre-headless | zulu-11, cloudstack-common (= ${source:Version}), net-tools, sudo, python3-mysql.connector, augeas-tools, mysql-client | mariadb-client, adduser, bzip2, ipmitool, file, gawk, iproute2, qemu-utils, python3-dnspython, lsb-release, init-system-helpers (>= 1.14~), python3-setuptools +Depends: ${python3:Depends}, openjdk-11-jre-headless | java11-runtime-headless | java11-runtime | openjdk-11-jre-headless | zulu-11, cloudstack-common (= ${source:Version}), net-tools, sudo, python3-mysql.connector, augeas-tools, mysql-client | mariadb-client, adduser, bzip2, ipmitool, file, gawk, iproute2, qemu-utils, python3-dnspython, lsb-release, init-system-helpers (>= 1.14~), python3-setuptools, libguestfs-tools Conflicts: cloud-server, cloud-client, cloud-client-ui Description: CloudStack server library The CloudStack management server diff --git a/engine/schema/pom.xml b/engine/schema/pom.xml index 0d0bee1a2af5..1258289db98b 100644 --- a/engine/schema/pom.xml +++ b/engine/schema/pom.xml @@ -74,7 +74,6 @@ def projectVersion = project.properties['project.systemvm.template.version'] - println(projectVersion) String[] versionParts = projectVersion.tokenize('.') pom.properties['cs.version'] = versionParts[0] + "." + versionParts[1] pom.properties['patch.version'] = versionParts[2] @@ -90,9 +89,7 @@ def csVersion = pom.properties['cs.version'] - println(csVersion) def patch = pom.properties['patch.version'] - println(patch) def templateList = [] templateList.add("systemvmtemplate-${csVersion}.${patch}-kvm") templateList.add("systemvmtemplate-${csVersion}.${patch}-vmware") @@ -102,10 +99,8 @@ File file = new File("./engine/schema/dist/systemvm-templates/md5sum.txt") def lines = file.readLines() for (template in templateList) { - println(template) def data = lines.findAll { it.contains(template) } if (data != null) { - println(template) def hypervisor = template.tokenize('-')[-1] pom.properties["$hypervisor" + ".checksum"] = data[0].tokenize(' ')[0] } @@ -193,32 +188,32 @@ ${kvm.checksum} - - download-vmware-template - - wget - - - true - - http://10.0.3.122/systemvmtemplate/custom/cks-debian/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-vmware.ova - ${basedir}/dist/systemvm-templates/ - ${vmware.checksum} - - - - download-xenserver-template - - wget - - - true - - http://10.0.3.122/systemvmtemplate/custom/cks-debian/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-xen.vhd.bz2 - ${basedir}/dist/systemvm-templates/ - ${xen.checksum} - - + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packaging/centos7/cloud.spec b/packaging/centos7/cloud.spec index 81ee8a77a82f..b2f77c5a83b2 100644 --- a/packaging/centos7/cloud.spec +++ b/packaging/centos7/cloud.spec @@ -79,6 +79,7 @@ Requires: /sbin/service Requires: /sbin/chkconfig Requires: /usr/bin/ssh-keygen Requires: genisoimage +Requires: libguestfs-tools Requires: ipmitool Requires: %{name}-common = %{_ver} Requires: iptables-services diff --git a/packaging/centos8/cloud.spec b/packaging/centos8/cloud.spec index 1a946ba0dd95..6a3627a57771 100644 --- a/packaging/centos8/cloud.spec +++ b/packaging/centos8/cloud.spec @@ -74,6 +74,7 @@ Requires: /sbin/service Requires: /sbin/chkconfig Requires: /usr/bin/ssh-keygen Requires: genisoimage +Requires: libguestfs-tools Requires: ipmitool Requires: %{name}-common = %{_ver} Requires: iptables-services diff --git a/packaging/suse15/cloud.spec b/packaging/suse15/cloud.spec index f355640c8650..77b6f6e95ac4 100644 --- a/packaging/suse15/cloud.spec +++ b/packaging/suse15/cloud.spec @@ -75,6 +75,7 @@ Requires: /sbin/service Requires: /sbin/chkconfig Requires: /usr/bin/ssh-keygen Requires: mkisofs +Requires: libguestfs-tools Requires: ipmitool Requires: %{name}-common = %{_ver} Requires: qemu-tools diff --git a/packaging/systemd/cloudstack-management.service b/packaging/systemd/cloudstack-management.service index b979f7f375a7..aedd3a170ae4 100644 --- a/packaging/systemd/cloudstack-management.service +++ b/packaging/systemd/cloudstack-management.service @@ -34,7 +34,9 @@ User=cloud EnvironmentFile=/etc/default/cloudstack-management WorkingDirectory=/var/log/cloudstack/management PIDFile=/var/run/cloudstack-management.pid +ExecStartPre=/bin/bash /usr/share/cloudstack-management/templates/systemvm/export-templates.sh ExecStart=/usr/bin/java $JAVA_DEBUG $JAVA_OPTS -cp $CLASSPATH $BOOTSTRAP_CLASS +TimeoutSec=900 [Install] WantedBy=multi-user.target diff --git a/scripts/installer/export-templates.sh b/scripts/installer/export-templates.sh new file mode 100644 index 000000000000..578854df437a --- /dev/null +++ b/scripts/installer/export-templates.sh @@ -0,0 +1,158 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +METADATA_FILE="metadata.ini" +IMAGE_PATH=${1:-"/usr/share/cloudstack-management/templates/systemvm/"} +TEMPLATE_VERSION=$(awk -F "=" '/version/ {print $2}' ${IMAGE_PATH}${METADATA_FILE} | xargs) +TEMPLATE_PATH="/usr/share/cloudstack-management/templates/systemvm/" +VERSION="${TEMPLATE_VERSION%.*}" +PREFIX=${2:-"systemvmtemplate-$VERSION"} +TEMP_IMAGE_PATH="/tmp/sysvm_convert/" + +if [ -f ${IMAGE_PATH}${PREFIX}-kvm.qcow2.bxz2 ]; then + mkdir -p $TEMP_IMAGE_PATH + cp -r $IMAGE_PATH/* $TEMP_IMAGE_PATH + cd $TEMP_IMAGE_PATH + bzip2 -dc $PREFIX-kvm.qcow2.bz2 > $PREFIX-kvm.qcow2 + # Export for KVM + virt-sparsify $PREFIX-kvm.qcow2 --compress -o compat=0.10 $PREFIX-kvm-temp.qcow2 + + # Export for VMware + qemu-img convert -f qcow2 -O vmdk -o adapter_type=lsilogic,subformat=streamOptimized,compat6 $PREFIX-kvm-temp.qcow2 $PREFIX-vmware.vmdk + size=$(stat --printf="%s" $PREFIX-vmware.vmdk) + +cat < $PREFIX-vmware.ovf + + + + + + + + Virtual disk information + + + + A virtual machine + $PREFIX-vmware + + The kind of installed guest operating system + + + Virtual hardware requirements + + Virtual Hardware Family + 0 + $PREFIX-vmware + vmx-11 + + + hertz * 10^6 + Number of Virtual CPUs + 1 virtual CPU(s) + 1 + 3 + 1 + + + byte * 2^20 + Memory Size + 256MB of memory + 2 + 4 + 256 + + + 0 + SCSI Controller + scsiController0 + 3 + lsilogic + 6 + + + 0 + IDE Controller + ideController0 + 4 + 5 + + + 0 + false + cdrom0 + 5 + 4 + 15 + + + 0 + disk0 + ovf:/disk/vmdisk1 + 6 + 3 + 17 + + + false + video + 7 + 24 + + + + + + false + vmci + 8 + vmware.vmci + 1 + + + + + + + + A human-readable annotation + $PREFIX-vmware + + + +EOF +cat < $PREFIX-vmware.mf +SHA1($PREFIX-vmware.ovf)= $(sha1sum $PREFIX-vmware.ovf|awk '{print $1}') +SHA1($PREFIX-vmware.vmdk)= $(sha1sum $PREFIX-vmware.vmdk |awk '{print $1}') +EOF + + tar -cvf $PREFIX-vmware.ova $PREFIX-vmware.ovf $PREFIX-vmware.mf $PREFIX-vmware.vmdk + checksum=$(md5sum $PREFIX-vmware.ova | awk '{print $1}') + sed -i '/^\['"vmware"']/,/^\[/{s/^checksum[[:space:]]*=.*/checksum = '"$checksum"'/}' ./$METADATA_FILE + + # Export for XenServer/XCP-ng + qemu-img convert -f qcow2 -O vpc $PREFIX-kvm.qcow2 $PREFIX-xen.vhd + bzip2 $PREFIX-xen.vhd + checksum=$(md5sum $PREFIX-xen.vhd.bz2 | awk '{print $1}') + sed -i '/^\['"xenserver"']/,/^\[/{s/^checksum[[:space:]]*=.*/checksum = '"$checksum"'/}' $METADATA_FILE + + rm -rf $PREFIX-kvm*.qcow2 $PREFIX-xen.vhd *.mf *.ovf *.vmdk + sudo cp $TEMP_IMAGE_PATH/$PREFIX* $TEMP_IMAGE_PATH/metadata.ini $IMAGE_PATH + cd - + rm -rf $TEMP_IMAGE_PATH +fi \ No newline at end of file diff --git a/scripts/util/keystore-cert-import b/scripts/util/keystore-cert-import index cbfd0b40e855..0a112e9303e8 100755 --- a/scripts/util/keystore-cert-import +++ b/scripts/util/keystore-cert-import @@ -91,8 +91,11 @@ fi # Import private key if available if [ ! -z "${PRIVKEY// }" ]; then echo "$PRIVKEY" > "$PRIVKEY_FILE" +else + > "$PRIVKEY_FILE" fi -if [ -f "$PRIVKEY_FILE" ]; then + +if [ -f "$PRIVKEY_FILE" ] && [ -s "$PRIVKEY_FILE" ]; then # Re-initialize keystore when private key is provided keytool -delete -noprompt -alias "$ALIAS" -keystore "$KS_FILE" -storepass "$KS_PASS" 2>/dev/null || true openssl pkcs12 -export -name "$ALIAS" -in "$CERT_FILE" -inkey "$PRIVKEY_FILE" -out "$KS_FILE.p12" -password pass:"$KS_PASS" > /dev/null 2>&1 diff --git a/systemvm/debian/opt/cloud/bin/setup/common.sh b/systemvm/debian/opt/cloud/bin/setup/common.sh index 82edc511e7fa..cfaeb941715e 100755 --- a/systemvm/debian/opt/cloud/bin/setup/common.sh +++ b/systemvm/debian/opt/cloud/bin/setup/common.sh @@ -593,13 +593,6 @@ routing_svcs() { fi } -setup_certificates() { - kspass=$(echo "$KEYSTORE_PSSWD"| base64 -d) - timeout 600 /opt/cloud/bin/keystore-cert-import /usr/local/cloud/systemvm/conf/agent.properties "$kspass" \ - /usr/local/cloud/systemvm/conf/cloud.jks ssh /usr/local/cloud/systemvm/conf/cloud.crt "" \ - /usr/local/cloud/systemvm/conf/cloud.ca.crt "" /usr/local/cloud/systemvm/conf/cloud.key "" -} - parse_cmd_line() { CMDLINE=$(cat /var/cache/cloud/cmdline) TYPE="unknown" diff --git a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh index 82e020f3b353..8006f6bb2445 100755 --- a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh +++ b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh @@ -37,13 +37,6 @@ setup_console_proxy() { enable_irqbalance 0 rm -f /etc/logrotate.d/cloud -# if [ -f /home/cloud/cloud.crt ]; then -# mv /home/cloud/cloud.crt /home/cloud/cloud.ca.crt /home/cloud/cloud.key /usr/local/cloud/systemvm/conf/ -# fi -# setup_certificates -# if [ $? -gt 0 ]; then -# log_it "Failed to setup CA Certificate for $TYPE" -# fi } setup_console_proxy diff --git a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh index 115521d17b2a..3b21ed5cae17 100755 --- a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh +++ b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh @@ -66,10 +66,6 @@ CORS setup_ntp rm -f /etc/logrotate.d/cloud -# setup_certificates -# if [ $? -gt 0 ]; then -# log_it "Failed to setup CA Certificate for $TYPE" -# fi } setup_secstorage From da5bba85282af80dcf8071f933eddd9d172f2139 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Wed, 19 Jan 2022 11:37:05 +0530 Subject: [PATCH 16/68] Add UI changes + move changes from patch file to runcmd --- .../admin/systemvm/PatchSystemVMCmd.java | 2 +- .../user/network/RestartNetworkCmd.java | 2 +- .../cloud/resource/ServerResourceBase.java | 4 +- .../orchestration/NetworkOrchestrator.java | 4 ++ .../upgrade/SystemVmTemplateRegistration.java | 10 ++- .../cluster/KubernetesClusterManagerImpl.java | 30 +++----- ...esClusterResourceModifierActionWorker.java | 71 +++++++++---------- .../KubernetesClusterStartWorker.java | 2 + .../cluster/CreateKubernetesClusterCmd.java | 8 --- .../resources/conf/k8s-control-node-add.yml | 19 +++++ .../main/resources/conf/k8s-control-node.yml | 19 +++++ .../src/main/resources/conf/k8s-node.yml | 19 +++++ .../debian/opt/cloud/bin/setup/cksnode.sh | 9 +-- ui/public/locales/en.json | 4 ++ ui/src/config/section/image.js | 1 - ui/src/config/section/infra/systemVms.js | 12 ++++ ui/src/config/section/network.js | 2 +- .../views/compute/CreateKubernetesCluster.vue | 8 --- .../java/com/cloud/utils/EncryptionUtil.java | 16 ----- .../utils/security/DigestHelper.java | 19 +++++ 20 files changed, 155 insertions(+), 106 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java index 481e62cffb54..0f08ad7f0a20 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java @@ -47,7 +47,7 @@ public class PatchSystemVMCmd extends BaseAsyncCmd { private Long id; @Parameter(name = ApiConstants.FORCED, type = CommandType.BOOLEAN, - description = "If true, initiates copy of scripts and restart of the agent if if the template version is the latest." + + description = "If true, initiates copy of scripts and restart of the agent, even if the scripts version matches." + "To be used with ID parameter only") private Boolean force; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java index 445130c4c333..52d659e1449d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java @@ -59,7 +59,7 @@ public class RestartNetworkCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.MAKEREDUNDANT, type = CommandType.BOOLEAN, required = false, description = "Turn the network into a network with redundant routers.", since = "4.11.1") private Boolean makeRedundant = false; - @Parameter(name = ApiConstants.LIVE_PATCH, type = CommandType.BOOLEAN, required = false, description = "Live Patch the router before restarting it", since = "4.16.1") + @Parameter(name = ApiConstants.LIVE_PATCH, type = CommandType.BOOLEAN, required = false, description = "Live Patch the router before restarting it. This parameter will work only when 'cleanup' is false.", since = "4.16.1") private Boolean livePatch = false; ///////////////////////////////////////////////////// diff --git a/core/src/main/java/com/cloud/resource/ServerResourceBase.java b/core/src/main/java/com/cloud/resource/ServerResourceBase.java index d8db1fd64605..99c9e2ee1058 100644 --- a/core/src/main/java/com/cloud/resource/ServerResourceBase.java +++ b/core/src/main/java/com/cloud/resource/ServerResourceBase.java @@ -33,8 +33,8 @@ import javax.naming.ConfigurationException; -import com.cloud.utils.EncryptionUtil; import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.cloudstack.utils.security.DigestHelper; import org.apache.log4j.Logger; import com.cloud.agent.IAgentControl; @@ -315,7 +315,7 @@ public String calculateCurrentChecksum(String name, String path) { if (cloudScriptsPath == null) { throw new CloudRuntimeException(String.format("Unable to find cloudScripts path, cannot update SystemVM %s", name)); } - String md5sum = EncryptionUtil.calculateChecksum(new File(cloudScriptsPath)); + String md5sum = DigestHelper.calculateChecksum(new File(cloudScriptsPath)); return md5sum; } } diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index 72073e92484f..ce80f4836bab 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -3300,6 +3300,10 @@ public boolean restartNetwork(final Long networkId, final Account callerAccount, for (DomainRouterVO router: domainRouters) { try { VMInstanceVO instanceVO = _vmDao.findById(router.getId()); + if (instanceVO == null) { + s_logger.info("Did not find a virtual router instance for the network"); + continue; + } Pair patched = mgr.updateSystemVM(instanceVO, true); if (patched.first()) { s_logger.info(String.format("Successfully patched router %s", router)); diff --git a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java index 4119b11ae508..214243886997 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java @@ -36,7 +36,6 @@ import com.cloud.upgrade.dao.BasicTemplateDataStoreDaoImpl; import com.cloud.user.Account; import com.cloud.utils.DateUtil; -import com.cloud.utils.EncryptionUtil; import com.cloud.utils.Pair; import com.cloud.utils.UriUtils; import com.cloud.utils.db.GlobalLock; @@ -55,6 +54,7 @@ import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; +import org.apache.cloudstack.utils.security.DigestHelper; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.ini4j.Ini; @@ -679,6 +679,12 @@ public void registerTemplate(Pair hypervisorA } } + /** + * This method parses the metadata file consisting of the systemVM templates information + * @return the version of the systemvm template that is to be used. This is done to in order + * to fallback on the latest available version of the systemVM template when there does not + * exist a template corresponding to the current code version. + */ public static String parseMetadataFile() { try { Ini ini = new Ini(); @@ -726,7 +732,7 @@ private void validateTemplates(Set hypervisorsInUse) } File tempFile = new File(TEMPLATES_PATH + matchedTemplate); - String templateChecksum = EncryptionUtil.calculateChecksum(tempFile); + String templateChecksum = DigestHelper.calculateChecksum(tempFile); if (!templateChecksum.equals(NewTemplateChecksum.get(getHypervisorType(hypervisor)))) { LOGGER.error(String.format("Checksum mismatch: %s != %s ", templateChecksum, NewTemplateChecksum.get(getHypervisorType(hypervisor)))); templatesFound = false; diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java index c11b19cb1efc..d79adb7d28fc 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java @@ -32,12 +32,11 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.google.common.base.Strings; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.annotation.AnnotationService; @@ -428,22 +427,19 @@ private boolean validateServiceOffering(final ServiceOffering serviceOffering, f private void validateDockerRegistryParams(final String dockerRegistryUserName, final String dockerRegistryPassword, - final String dockerRegistryUrl, - final String dockerRegistryEmail) { + final String dockerRegistryUrl) { // if no params related to docker registry specified then nothing to validate so return true if ((dockerRegistryUserName == null || dockerRegistryUserName.isEmpty()) && (dockerRegistryPassword == null || dockerRegistryPassword.isEmpty()) && - (dockerRegistryUrl == null || dockerRegistryUrl.isEmpty()) && - (dockerRegistryEmail == null || dockerRegistryEmail.isEmpty())) { + (dockerRegistryUrl == null || dockerRegistryUrl.isEmpty())) { return; } // all params related to docker registry must be specified or nothing if (!((dockerRegistryUserName != null && !dockerRegistryUserName.isEmpty()) && (dockerRegistryPassword != null && !dockerRegistryPassword.isEmpty()) && - (dockerRegistryUrl != null && !dockerRegistryUrl.isEmpty()) && - (dockerRegistryEmail != null && !dockerRegistryEmail.isEmpty()))) { - throw new InvalidParameterValueException("All the docker private registry parameters (username, password, url, email) required are specified"); + (dockerRegistryUrl != null && !dockerRegistryUrl.isEmpty()))) { + throw new InvalidParameterValueException("All the docker private registry parameters (username, password, url) required are specified"); } try { @@ -451,12 +447,6 @@ private void validateDockerRegistryParams(final String dockerRegistryUserName, } catch (MalformedURLException e) { throw new InvalidParameterValueException("Invalid docker registry url specified"); } - - Pattern VALID_EMAIL_ADDRESS_REGEX = Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", Pattern.CASE_INSENSITIVE); - Matcher matcher = VALID_EMAIL_ADDRESS_REGEX.matcher(dockerRegistryEmail); - if (!matcher.find()) { - throw new InvalidParameterValueException("Invalid docker registry email specified"); - } } private DeployDestination plan(final long nodesCount, final DataCenter zone, final ServiceOffering offering) throws InsufficientServerCapacityException { @@ -619,7 +609,6 @@ private void validateKubernetesClusterCreateParameters(final CreateKubernetesClu final String dockerRegistryUserName = cmd.getDockerRegistryUserName(); final String dockerRegistryPassword = cmd.getDockerRegistryPassword(); final String dockerRegistryUrl = cmd.getDockerRegistryUrl(); - final String dockerRegistryEmail = cmd.getDockerRegistryEmail(); final Long nodeRootDiskSize = cmd.getNodeRootDiskSize(); final String externalLoadBalancerIpAddress = cmd.getExternalLoadBalancerIpAddress(); @@ -706,7 +695,7 @@ private void validateKubernetesClusterCreateParameters(final CreateKubernetesClu throw new InvalidParameterValueException("Given service offering ID: %s is not suitable for Kubernetes cluster"); } - validateDockerRegistryParams(dockerRegistryUserName, dockerRegistryPassword, dockerRegistryUrl, dockerRegistryEmail); + validateDockerRegistryParams(dockerRegistryUserName, dockerRegistryPassword, dockerRegistryUrl); Network network = null; if (networkId != null) { @@ -728,7 +717,8 @@ private void validateKubernetesClusterCreateParameters(final CreateKubernetesClu } } - if (!KubernetesClusterExperimentalFeaturesEnabled.value() && !StringUtils.isAllEmpty(dockerRegistryUrl, dockerRegistryUserName, dockerRegistryEmail, dockerRegistryPassword)) { + if (!KubernetesClusterExperimentalFeaturesEnabled.value() && (!Strings.isNullOrEmpty(dockerRegistryUrl) || + !Strings.isNullOrEmpty(dockerRegistryUserName) || !Strings.isNullOrEmpty(dockerRegistryPassword))) { throw new CloudRuntimeException(String.format("Private registry for the Kubernetes cluster is an experimental feature. Use %s configuration for enabling experimental features", KubernetesClusterExperimentalFeaturesEnabled.key())); } } @@ -778,7 +768,6 @@ private void addKubernetesClusterDetails(final KubernetesCluster kubernetesClust final String dockerRegistryUserName = cmd.getDockerRegistryUserName(); final String dockerRegistryPassword = cmd.getDockerRegistryPassword(); final String dockerRegistryUrl = cmd.getDockerRegistryUrl(); - final String dockerRegistryEmail = cmd.getDockerRegistryEmail(); final boolean networkCleanup = cmd.getNetworkId() == null; Transaction.execute(new TransactionCallbackNoReturn() { @Override @@ -793,9 +782,8 @@ public void doInTransactionWithoutResult(TransactionStatus status) { addKubernetesClusterDetailIfIsNotEmpty(details, kubernetesClusterId, ApiConstants.DOCKER_REGISTRY_USER_NAME, dockerRegistryUserName, true); addKubernetesClusterDetailIfIsNotEmpty(details, kubernetesClusterId, ApiConstants.DOCKER_REGISTRY_PASSWORD, dockerRegistryPassword, false); addKubernetesClusterDetailIfIsNotEmpty(details, kubernetesClusterId, ApiConstants.DOCKER_REGISTRY_URL, dockerRegistryUrl, true); - addKubernetesClusterDetailIfIsNotEmpty(details, kubernetesClusterId, ApiConstants.DOCKER_REGISTRY_EMAIL, dockerRegistryEmail, true); - details.add(new KubernetesClusterDetailsVO(kubernetesClusterId, ApiConstants.USERNAME, "admin", true)); + details.add(new KubernetesClusterDetailsVO(kubernetesCluster.getId(), ApiConstants.USERNAME, "admin", true)); SecureRandom random = new SecureRandom(); String randomPassword = new BigInteger(130, random).toString(32); details.add(new KubernetesClusterDetailsVO(kubernetesClusterId, ApiConstants.PASSWORD, randomPassword, false)); diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java index 8a6c81e23ee1..591b90178939 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java @@ -28,6 +28,7 @@ import javax.inject.Inject; +import com.google.common.base.Strings; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.command.user.firewall.CreateFirewallRuleCmd; @@ -35,6 +36,7 @@ import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd; import org.apache.commons.codec.binary.Base64; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Level; import com.cloud.capacity.CapacityManager; @@ -95,7 +97,6 @@ import com.cloud.vm.UserVmManager; import com.cloud.vm.VirtualMachine; import com.cloud.vm.dao.VMInstanceDao; -import org.apache.commons.lang3.StringUtils; import static com.cloud.utils.NumbersUtil.toHumanReadableSize; @@ -163,54 +164,48 @@ private String getKubernetesNodeConfig(final String joinIp, final boolean ejectI k8sNodeConfig = k8sNodeConfig.replace(joinIpKey, joinIp); k8sNodeConfig = k8sNodeConfig.replace(clusterTokenKey, KubernetesClusterUtil.generateClusterToken(kubernetesCluster)); k8sNodeConfig = k8sNodeConfig.replace(ejectIsoKey, String.valueOf(ejectIso)); - /* genarate /.docker/config.json file on the nodes only if Kubernetes cluster is created to + + k8sNodeConfig = updateKubeConfigWithRegistryDetails(k8sNodeConfig); + return k8sNodeConfig; + } + + protected String updateKubeConfigWithRegistryDetails(String k8sConfig) { + /* genarate /etc/containerd/config.toml file on the nodes only if Kubernetes cluster is created to * use docker private registry */ - String dockerUserName = null; - String dockerPassword = null; - String dockerRegistryUrl = null; - String dockerRegistryEmail = null; + String registryUsername = null; + String registryPassword = null; + String registryUrl = null; + List details = kubernetesClusterDetailsDao.listDetails(kubernetesCluster.getId()); for (KubernetesClusterDetailsVO detail : details) { if (detail.getName().equals(ApiConstants.DOCKER_REGISTRY_USER_NAME)) { - dockerUserName = detail.getValue(); + registryUsername = detail.getValue(); } if (detail.getName().equals(ApiConstants.DOCKER_REGISTRY_PASSWORD)) { - dockerPassword = detail.getValue(); + registryPassword = detail.getValue(); } if (detail.getName().equals(ApiConstants.DOCKER_REGISTRY_URL)) { - dockerRegistryUrl = detail.getValue(); - } - if (detail.getName().equals(ApiConstants.DOCKER_REGISTRY_EMAIL)) { - dockerRegistryEmail = detail.getValue(); + registryUrl = detail.getValue(); } } - if (StringUtils.isNoneEmpty(dockerUserName, dockerPassword)) { - // do write file for /.docker/config.json through the code instead of k8s-node.yml as we can no make a section - // optional or conditionally applied - String dockerConfigString = "write_files:\n" + - " - path: /.docker/config.json\n" + - " owner: cloud:cloud\n" + - " permissions: '0644'\n" + - " content: |\n" + - " {\n" + - " \"auths\": {\n" + - " {{docker.url}}: {\n" + - " \"auth\": {{docker.secret}},\n" + - " \"email\": {{docker.email}}\n" + - " }\n" + - " }\n" + - " }"; - k8sNodeConfig = k8sNodeConfig.replace("write_files:", dockerConfigString); - final String dockerUrlKey = "{{docker.url}}"; - final String dockerAuthKey = "{{docker.secret}}"; - final String dockerEmailKey = "{{docker.email}}"; - final String usernamePasswordKey = dockerUserName + ":" + dockerPassword; - String base64Auth = Base64.encodeBase64String(usernamePasswordKey.getBytes(com.cloud.utils.StringUtils.getPreferredCharset())); - k8sNodeConfig = k8sNodeConfig.replace(dockerUrlKey, "\"" + dockerRegistryUrl + "\""); - k8sNodeConfig = k8sNodeConfig.replace(dockerAuthKey, "\"" + base64Auth + "\""); - k8sNodeConfig = k8sNodeConfig.replace(dockerEmailKey, "\"" + dockerRegistryEmail + "\""); + + if (!Strings.isNullOrEmpty(registryUsername) && !Strings.isNullOrEmpty(registryPassword) && !Strings.isNullOrEmpty(registryUrl)) { + // Update runcmd in the cloud-init configuration to run a script that updates the containerd config with provided registry details + String runCmd = "- bash -x /opt/bin/setup-containerd"; + + String registryEp = registryUrl.split("://")[1]; + k8sConfig = k8sConfig.replace("- containerd config default > /etc/containerd/config.toml", runCmd); + final String registryUrlKey = "{{registry.url}}"; + final String registryUrlEpKey = "{{registry.url.endpoint}}"; + final String registryAuthKey = "{{registry.token}}"; + + final String usernamePasswordKey = registryUsername + ":" + registryPassword; + String base64Auth = Base64.encodeBase64String(usernamePasswordKey.getBytes((com.cloud.utils.StringUtils.getPreferredCharset()))); + k8sConfig = k8sConfig.replace(registryUrlKey, registryUrl); + k8sConfig = k8sConfig.replace(registryUrlEpKey, registryEp); + k8sConfig = k8sConfig.replace(registryAuthKey, base64Auth); } - return k8sNodeConfig; + return k8sConfig; } protected DeployDestination plan(final long nodesCount, final DataCenter zone, final ServiceOffering offering) throws InsufficientServerCapacityException { diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java index 9bed248f7b52..e2496a04c25b 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java @@ -174,6 +174,7 @@ private String getKubernetesControlNodeConfig(final String controlNodeIp, final initArgs += String.format(" --kubernetes-version=%s", getKubernetesClusterVersion().getSemanticVersion()); k8sControlNodeConfig = k8sControlNodeConfig.replace(clusterInitArgsKey, initArgs); k8sControlNodeConfig = k8sControlNodeConfig.replace(ejectIsoKey, String.valueOf(ejectIso)); + k8sControlNodeConfig = updateKubeConfigWithRegistryDetails(k8sControlNodeConfig); return k8sControlNodeConfig; } @@ -236,6 +237,7 @@ private String getKubernetesAdditionalControlNodeConfig(final String joinIp, fin k8sControlNodeConfig = k8sControlNodeConfig.replace(clusterTokenKey, KubernetesClusterUtil.generateClusterToken(kubernetesCluster)); k8sControlNodeConfig = k8sControlNodeConfig.replace(clusterHACertificateKey, KubernetesClusterUtil.generateClusterHACertificateKey(kubernetesCluster)); k8sControlNodeConfig = k8sControlNodeConfig.replace(ejectIsoKey, String.valueOf(ejectIso)); + k8sControlNodeConfig = updateKubeConfigWithRegistryDetails(k8sControlNodeConfig); return k8sControlNodeConfig; } diff --git a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/CreateKubernetesClusterCmd.java b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/CreateKubernetesClusterCmd.java index 376c148abb7a..64de4669f870 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/CreateKubernetesClusterCmd.java +++ b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/CreateKubernetesClusterCmd.java @@ -140,10 +140,6 @@ public class CreateKubernetesClusterCmd extends BaseAsyncCreateCmd { description = "URL for the docker image private registry") private String dockerRegistryUrl; - @Parameter(name = ApiConstants.DOCKER_REGISTRY_EMAIL, type = CommandType.STRING, - description = "email of the docker image private registry user") - private String dockerRegistryEmail; - @Parameter(name = ApiConstants.NODE_ROOT_DISK_SIZE, type = CommandType.LONG, description = "root disk size in GB for each node") private Long nodeRootDiskSize; @@ -226,10 +222,6 @@ public String getDockerRegistryUrl() { return dockerRegistryUrl; } - public String getDockerRegistryEmail() { - return dockerRegistryEmail; - } - public Long getNodeRootDiskSize() { if (nodeRootDiskSize != null) { if (nodeRootDiskSize < DEFAULT_NODE_ROOT_DISK_SIZE) { diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml index db295188eba5..480e7bba8526 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml @@ -213,6 +213,23 @@ write_files: sudo touch /home/cloud/success echo "true" > /home/cloud/success + - path: /opt/bin/setup-containerd + permissions: '0755' + owner: root:root + content: | + #!/bin/bash -e + + export registryConfig="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.mirrors.\"{{registry.url.endpoint}}\"]\n \\ endpoint = [\"{{registry.url}}\"]" + export registryCredentials="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.configs.\"{{registry.url}}\".auth]\n \tauth = \"\" \n \tidentitytoken = \"{{registry.token}}\"" + + echo "creating config file for containerd" + containerd config default > /etc/containerd/config.toml + sed -i '/\[plugins."io.containerd.grpc.v1.cri".registry\]/a '"${registryCredentials}"'' /etc/containerd/config.toml + sed -i '/\[plugins."io.containerd.grpc.v1.cri".registry.mirrors\]/a '"${registryConfig}"'' /etc/containerd/config.toml + + echo "Restarting containerd service" + systemctl restart containerd + - path: /etc/systemd/system/setup-kube-system.service permissions: '0755' owner: root:root @@ -242,6 +259,8 @@ write_files: runcmd: - chown -R cloud:cloud /home/cloud/.ssh + - containerd config default > /etc/containerd/config.toml + - systemctl restart containerd - [ systemctl, start, setup-kube-system ] - [ systemctl, start, deploy-kube-system ] diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml index 730477bd4eef..ceca597516fa 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml @@ -270,6 +270,23 @@ write_files: sudo touch /home/cloud/success echo "true" > /home/cloud/success + - path: /opt/bin/setup-containerd + permissions: '0755' + owner: root:root + content: | + #!/bin/bash -e + + export registryConfig="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.mirrors.\"{{registry.url.endpoint}}\"]\n \\ endpoint = [\"{{registry.url}}\"]" + export registryCredentials="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.configs.\"{{registry.url.endpoint}}\".auth]\n \tauth = \"\" \n \tidentitytoken = \"{{registry.token}}\"" + + echo "creating config file for containerd" + containerd config default > /etc/containerd/config.toml + sed -i '/\[plugins."io.containerd.grpc.v1.cri".registry\]/a '"${registryCredentials}"'' /etc/containerd/config.toml + sed -i '/\[plugins."io.containerd.grpc.v1.cri".registry.mirrors\]/a '"${registryConfig}"'' /etc/containerd/config.toml + + echo "Restarting containerd service" + systemctl restart containerd + - path: /etc/systemd/system/setup-kube-system.service permissions: '0755' owner: root:root @@ -299,6 +316,8 @@ write_files: runcmd: - chown -R cloud:cloud /home/cloud/.ssh + - containerd config default > /etc/containerd/config.toml + - systemctl restart containerd - [ systemctl, start, setup-kube-system ] - [ systemctl, start, deploy-kube-system ] diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml index eea369921ac8..b6a71e8deb2e 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml @@ -213,6 +213,23 @@ write_files: sudo touch /home/cloud/success echo "true" > /home/cloud/success + - path: /opt/bin/setup-containerd + permissions: '0755' + owner: root:root + content: | + #!/bin/bash -e + + export registryConfig="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.mirrors.\"{{registry.url.endpoint}}\"]\n \\ endpoint = [\"{{registry.url}}\"]" + export registryCredentials="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.configs.\"{{registry.url}}\".auth]\n \tauth = \"\" \n \tidentitytoken = \"{{registry.token}}\"" + + echo "creating config file for containerd" + containerd config default > /etc/containerd/config.toml + sed -i '/\[plugins."io.containerd.grpc.v1.cri".registry\]/a '"${registryCredentials}"'' /etc/containerd/config.toml + sed -i '/\[plugins."io.containerd.grpc.v1.cri".registry.mirrors\]/a '"${registryConfig}"'' /etc/containerd/config.toml + + echo "Restarting containerd service" + systemctl restart containerd + - path: /etc/systemd/system/setup-kube-system.service permissions: '0755' owner: root:root @@ -242,5 +259,7 @@ write_files: runcmd: - chown -R cloud:cloud /home/cloud/.ssh + - containerd config default > /etc/containerd/config.toml + - systemctl restart containerd - [ systemctl, start, setup-kube-system ] - [ systemctl, start, deploy-kube-system ] diff --git a/systemvm/debian/opt/cloud/bin/setup/cksnode.sh b/systemvm/debian/opt/cloud/bin/setup/cksnode.sh index 78ae96631ad9..0b5df04ded2b 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cksnode.sh +++ b/systemvm/debian/opt/cloud/bin/setup/cksnode.sh @@ -31,15 +31,10 @@ setup_k8s_node() { systemctl restart ssh # Prevent root login -# > /root/.ssh/authorized_keys -# passwd -l root + > /root/.ssh/authorized_keys + passwd -l root #sed -i 's#root:x:0:0:root:/root:/bin/bash#root:x:0:0:root:/root:/sbin/nologin#' /etc/passwd - # Update containerd configuration - mkdir -p /etc/containerd - containerd config default>/etc/containerd/config.toml - systemctl restart containerd - swapoff -a sudo sed -i '/ swap / s/^/#/' /etc/fstab log_it "Swap disabled" diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 76e2f35ced56..ae67155f753f 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -230,6 +230,8 @@ "label.action.migrate.systemvm": "Migrate System VM", "label.action.migrate.systemvm.processing": "Migrating System VM....", "label.action.migrate.systemvm.to.ps": "Migrate system VM to another primary storage", +"label.action.patch.systemvm": "Patch System VM", +"label.action.patch.systemvm.processing": "Patching System VM....", "label.action.project.add.account": "Add Account to Project", "label.action.project.add.user": "Add User to Project", "label.action.reboot.instance": "Reboot Instance", @@ -1317,6 +1319,7 @@ "label.list.nodes": "List nodes", "label.list.pods": "List pods", "label.list.services": "List services", +"label.livepatch": "Live Patch network's router(s)", "label.load.balancer": "Load Balancer", "label.load.balancing.policies": "Load balancing policies", "label.loadbalancerinstance": "Assigned VMs", @@ -2562,6 +2565,7 @@ "message.action.host.enable.maintenance.mode": "Enabling maintenance mode will cause a live migration of all running instances on this host to any available host.", "message.action.instance.reset.password": "Please confirm that you want to change the ROOT password for this virtual machine.", "message.action.manage.cluster": "Please confirm that you want to manage the cluster.", +"message.action.patch.systemvm": "Please confirm that you want to patch the System VM.", "message.action.primarystorage.enable.maintenance.mode": "Warning: placing the primary storage into maintenance mode will cause all VMs using volumes from it to be stopped. Do you want to continue?", "message.action.reboot.instance": "Please confirm that you want to reboot this instance.", "message.action.reboot.router": "All services provided by this virtual router will be interrupted. Please confirm that you want to reboot this router.", diff --git a/ui/src/config/section/image.js b/ui/src/config/section/image.js index 360525397f6e..3bd6d578cd75 100644 --- a/ui/src/config/section/image.js +++ b/ui/src/config/section/image.js @@ -100,7 +100,6 @@ export default { return (['Admin'].includes(store.userInfo.roletype) || // If admin or owner or belongs to current project (record.domainid === store.userInfo.domainid && record.account === store.userInfo.account) || (record.domainid === store.userInfo.domainid && record.projectid && store.project && store.project.id && record.projectid === store.project.id)) && - record.templatetype !== 'SYSTEM' && record.isready }, popup: true, diff --git a/ui/src/config/section/infra/systemVms.js b/ui/src/config/section/infra/systemVms.js index 2c0bd1d6e593..acd1f1959787 100644 --- a/ui/src/config/section/infra/systemVms.js +++ b/ui/src/config/section/infra/systemVms.js @@ -135,6 +135,18 @@ export default { }, response: (result) => { return result && result.diagnostics && result.diagnostics.url ? `Please click the link to download the retrieved diagnostics:

${result.diagnostics.url}

` : 'Invalid response' } }, + { + api: 'patchSystemVm', + icon: 'diff', + label: 'label.action.patch.systemvm', + message: 'message.action.patch.systemvm', + dataView: true, + show: (record) => { return ['Running'].includes(record.state) }, + args: ['forced'], + groupAction: true, + popup: true, + groupMap: (selection) => { return selection.map(x => { return { id: x } }) } + }, { api: 'destroySystemVm', icon: 'delete', diff --git a/ui/src/config/section/network.js b/ui/src/config/section/network.js index 95c24159bb07..5928c6eee24b 100644 --- a/ui/src/config/section/network.js +++ b/ui/src/config/section/network.js @@ -99,7 +99,7 @@ export default { label: 'label.restart.network', message: 'message.restart.network', dataView: true, - args: ['cleanup'], + args: ['cleanup', 'livepatch'], show: (record) => record.type !== 'L2', groupAction: true, popup: true, diff --git a/ui/src/views/compute/CreateKubernetesCluster.vue b/ui/src/views/compute/CreateKubernetesCluster.vue index 6b6b81f67918..52aa831d75c5 100644 --- a/ui/src/views/compute/CreateKubernetesCluster.vue +++ b/ui/src/views/compute/CreateKubernetesCluster.vue @@ -226,14 +226,6 @@ }]" :placeholder="apiParams.dockerregistryurl.description"/> - - - -
diff --git a/utils/src/main/java/com/cloud/utils/EncryptionUtil.java b/utils/src/main/java/com/cloud/utils/EncryptionUtil.java index ff791a3f5226..b82842e947b6 100644 --- a/utils/src/main/java/com/cloud/utils/EncryptionUtil.java +++ b/utils/src/main/java/com/cloud/utils/EncryptionUtil.java @@ -18,12 +18,7 @@ */ package com.cloud.utils; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; import java.io.UnsupportedEncodingException; -import java.nio.file.Files; -import java.nio.file.Paths; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -31,7 +26,6 @@ import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; -import org.apache.commons.codec.digest.DigestUtils; import org.apache.log4j.Logger; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; @@ -76,14 +70,4 @@ public static String generateSignature(String data, String key) { throw new CloudRuntimeException("unable to generate signature", e); } } - - public static String calculateChecksum(File file) { - try (InputStream is = Files.newInputStream(Paths.get(file.getPath()))) { - return DigestUtils.md5Hex(is); - } catch (IOException e) { - String errMsg = "Failed to calculate template checksum"; - s_logger.error(errMsg, e); - throw new CloudRuntimeException(errMsg, e); - } - } } diff --git a/utils/src/main/java/org/apache/cloudstack/utils/security/DigestHelper.java b/utils/src/main/java/org/apache/cloudstack/utils/security/DigestHelper.java index 8fd8e8f338ef..7e4e80f8f4d2 100644 --- a/utils/src/main/java/org/apache/cloudstack/utils/security/DigestHelper.java +++ b/utils/src/main/java/org/apache/cloudstack/utils/security/DigestHelper.java @@ -17,10 +17,17 @@ package org.apache.cloudstack.utils.security; import org.apache.commons.lang3.StringUtils; +import com.cloud.utils.EncryptionUtil; +import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.log4j.Logger; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; +import java.nio.file.Files; +import java.nio.file.Paths; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.HashMap; @@ -28,6 +35,8 @@ public class DigestHelper { + public static final Logger LOGGER = Logger.getLogger(EncryptionUtil.class.getName()); + public static ChecksumValue digest(String algorithm, InputStream is) throws NoSuchAlgorithmException, IOException { MessageDigest digest = MessageDigest.getInstance(algorithm); ChecksumValue checksum = null; @@ -131,4 +140,14 @@ protected static boolean isAlgorithmPresent(String checksum) { public static String getHashValueFromChecksumValue(String checksum) { return isAlgorithmPresent(checksum) ? new ChecksumValue(checksum).getChecksum() : checksum; } + + public static String calculateChecksum(File file) { + try (InputStream is = Files.newInputStream(Paths.get(file.getPath()))) { + return DigestUtils.md5Hex(is); + } catch (IOException e) { + String errMsg = "Failed to calculate template checksum"; + LOGGER.error(errMsg, e); + throw new CloudRuntimeException(errMsg, e); + } + } } From 0ccf346435d59e424de28fbcae373029fdfef758 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Wed, 19 Jan 2022 16:35:01 +0530 Subject: [PATCH 17/68] test: validate performance for template modification during seeding --- .../upgrade/SystemVmTemplateRegistration.java | 18 +++++++ .../systemd/cloudstack-management.service | 1 - .../cluster/KubernetesClusterManagerImpl.java | 4 +- ...esClusterResourceModifierActionWorker.java | 3 +- pom.xml | 2 +- scripts/installer/export-templates.sh | 54 +++++++++++++++---- .../apache/cloudstack/ca/CAManagerImpl.java | 3 +- tools/appliance/build.sh | 8 +-- 8 files changed, 70 insertions(+), 23 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java index 214243886997..2df2de44995e 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java @@ -93,6 +93,7 @@ public class SystemVmTemplateRegistration { public static final String TEMPORARY_SECONDARY_STORE = "tmp"; private static final String PARTIAL_TEMPLATE_FOLDER = String.format("/template/tmpl/%d/", Account.ACCOUNT_ID_SYSTEM); private static final String storageScriptsDir = "scripts/storage/secondary"; + private static final String installerScriptsDir = "scripts/installer/"; private static final Integer OTHER_LINUX_ID = 99; private static final Integer LINUX_5_ID = 15; private static final Integer LINUX_7_ID = 183; @@ -724,6 +725,7 @@ private void validateTemplates(Set hypervisorsInUse) } boolean templatesFound = true; + int count = hypervisors.size(); for (String hypervisor : hypervisors) { String matchedTemplate = templates.stream().filter(x -> x.contains(hypervisor)).findAny().orElse(null); if (matchedTemplate == null) { @@ -732,6 +734,22 @@ private void validateTemplates(Set hypervisorsInUse) } File tempFile = new File(TEMPLATES_PATH + matchedTemplate); + if (!tempFile.exists()) { + --count; + String exportTmpltScript = Script.findScript(installerScriptsDir, "export-templates.sh"); + if (exportTmpltScript == null) { + throw new CloudRuntimeException("Unable to find the export-templates.sh script to export templates on the fly"); + } + Script scr = new Script(exportTmpltScript, SCRIPT_TIMEOUT, LOGGER); + scr.add(hypervisor.toLowerCase(Locale.ROOT)); + scr.add((count > 0 ? "1" : "0")); + String result = scr.execute(); + if (result != null) { + String errMsg = String.format("failed to create template: %s ", result); + LOGGER.error(errMsg); + throw new CloudRuntimeException(errMsg); + } + } String templateChecksum = DigestHelper.calculateChecksum(tempFile); if (!templateChecksum.equals(NewTemplateChecksum.get(getHypervisorType(hypervisor)))) { LOGGER.error(String.format("Checksum mismatch: %s != %s ", templateChecksum, NewTemplateChecksum.get(getHypervisorType(hypervisor)))); diff --git a/packaging/systemd/cloudstack-management.service b/packaging/systemd/cloudstack-management.service index aedd3a170ae4..db94a42d6439 100644 --- a/packaging/systemd/cloudstack-management.service +++ b/packaging/systemd/cloudstack-management.service @@ -34,7 +34,6 @@ User=cloud EnvironmentFile=/etc/default/cloudstack-management WorkingDirectory=/var/log/cloudstack/management PIDFile=/var/run/cloudstack-management.pid -ExecStartPre=/bin/bash /usr/share/cloudstack-management/templates/systemvm/export-templates.sh ExecStart=/usr/bin/java $JAVA_DEBUG $JAVA_OPTS -cp $CLASSPATH $BOOTSTRAP_CLASS TimeoutSec=900 diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java index d79adb7d28fc..c19968d43662 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java @@ -36,7 +36,6 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.google.common.base.Strings; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.annotation.AnnotationService; @@ -717,8 +716,7 @@ private void validateKubernetesClusterCreateParameters(final CreateKubernetesClu } } - if (!KubernetesClusterExperimentalFeaturesEnabled.value() && (!Strings.isNullOrEmpty(dockerRegistryUrl) || - !Strings.isNullOrEmpty(dockerRegistryUserName) || !Strings.isNullOrEmpty(dockerRegistryPassword))) { + if (!KubernetesClusterExperimentalFeaturesEnabled.value() && !StringUtils.isAllEmpty(dockerRegistryUrl, dockerRegistryUserName, dockerRegistryPassword)) { throw new CloudRuntimeException(String.format("Private registry for the Kubernetes cluster is an experimental feature. Use %s configuration for enabling experimental features", KubernetesClusterExperimentalFeaturesEnabled.key())); } } diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java index 591b90178939..98e4587dff37 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java @@ -28,7 +28,6 @@ import javax.inject.Inject; -import com.google.common.base.Strings; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.command.user.firewall.CreateFirewallRuleCmd; @@ -189,7 +188,7 @@ protected String updateKubeConfigWithRegistryDetails(String k8sConfig) { } } - if (!Strings.isNullOrEmpty(registryUsername) && !Strings.isNullOrEmpty(registryPassword) && !Strings.isNullOrEmpty(registryUrl)) { + if (StringUtils.isNoneEmpty(registryUsername, registryPassword, registryUrl)) { // Update runcmd in the cloud-init configuration to run a script that updates the containerd config with provided registry details String runCmd = "- bash -x /opt/bin/setup-containerd"; diff --git a/pom.xml b/pom.xml index 4daaa8ccfca5..a704d520c097 100644 --- a/pom.xml +++ b/pom.xml @@ -49,7 +49,7 @@ UTF-8 UTF-8 - 4.16.1.0 + 4.17.0.0 11 diff --git a/scripts/installer/export-templates.sh b/scripts/installer/export-templates.sh index 578854df437a..9371f1c74128 100644 --- a/scripts/installer/export-templates.sh +++ b/scripts/installer/export-templates.sh @@ -17,21 +17,27 @@ # under the License. METADATA_FILE="metadata.ini" -IMAGE_PATH=${1:-"/usr/share/cloudstack-management/templates/systemvm/"} +IMAGE_PATH=${3:-"/usr/share/cloudstack-management/templates/systemvm/"} TEMPLATE_VERSION=$(awk -F "=" '/version/ {print $2}' ${IMAGE_PATH}${METADATA_FILE} | xargs) TEMPLATE_PATH="/usr/share/cloudstack-management/templates/systemvm/" VERSION="${TEMPLATE_VERSION%.*}" -PREFIX=${2:-"systemvmtemplate-$VERSION"} +PREFIX=${4:-"systemvmtemplate-$VERSION"} +CLEANUP=${2:-1} TEMP_IMAGE_PATH="/tmp/sysvm_convert/" -if [ -f ${IMAGE_PATH}${PREFIX}-kvm.qcow2.bxz2 ]; then +initial_setup() { mkdir -p $TEMP_IMAGE_PATH cp -r $IMAGE_PATH/* $TEMP_IMAGE_PATH cd $TEMP_IMAGE_PATH - bzip2 -dc $PREFIX-kvm.qcow2.bz2 > $PREFIX-kvm.qcow2 + if [ ! -f ${TEMP_IMAGE_PATH}${PREFIX}-kvm.qcow2 ]; then + bzip2 -dc $PREFIX-kvm.qcow2.bz2 > $PREFIX-kvm.qcow2 + fi +} + +export_vmware() { + initial_setup # Export for KVM virt-sparsify $PREFIX-kvm.qcow2 --compress -o compat=0.10 $PREFIX-kvm-temp.qcow2 - # Export for VMware qemu-img convert -f qcow2 -O vmdk -o adapter_type=lsilogic,subformat=streamOptimized,compat6 $PREFIX-kvm-temp.qcow2 $PREFIX-vmware.vmdk size=$(stat --printf="%s" $PREFIX-vmware.vmdk) @@ -144,15 +150,43 @@ EOF tar -cvf $PREFIX-vmware.ova $PREFIX-vmware.ovf $PREFIX-vmware.mf $PREFIX-vmware.vmdk checksum=$(md5sum $PREFIX-vmware.ova | awk '{print $1}') sed -i '/^\['"vmware"']/,/^\[/{s/^checksum[[:space:]]*=.*/checksum = '"$checksum"'/}' ./$METADATA_FILE + rm -rf *.mf *.ovf *.vmdk + sudo cp $TEMP_IMAGE_PATH/$PREFIX-vmware.ova $TEMP_IMAGE_PATH/metadata.ini $IMAGE_PATH + cleanup +} +export_xen() { # Export for XenServer/XCP-ng + initial_setup qemu-img convert -f qcow2 -O vpc $PREFIX-kvm.qcow2 $PREFIX-xen.vhd bzip2 $PREFIX-xen.vhd checksum=$(md5sum $PREFIX-xen.vhd.bz2 | awk '{print $1}') sed -i '/^\['"xenserver"']/,/^\[/{s/^checksum[[:space:]]*=.*/checksum = '"$checksum"'/}' $METADATA_FILE + rm -rf $PREFIX-xen.vhd + sudo cp $TEMP_IMAGE_PATH/$PREFIX-xen* $TEMP_IMAGE_PATH/metadata.ini $IMAGE_PATH + cleanup +} + +cleanup() { + cd /var/cloudstack/management/ + if [ $CLEANUP == 1 ]; then + cd /var/cloudstack/management/ + rm -rf $TEMP_IMAGE_PATH + fi +} + +if [ "$#" -lt 1 ] ; then + echo "Usage: $0 [cleanup: 0/1; default: 1] [imagepath: default:/usr/share/cloudstack-management/templates/systemvm/] [templateprefix: default:systemvmtemplate-$VERSION]" >&2 + exit 1 +fi + +if [ $1 == "vmware" ]; then + echo "exporting vmware template" + export_vmware +elif [ $1 == "xenserver" ]; then + echo "exporting xenserver template" + export_xen +else + echo "Conversion of template to $1's compatible format not supported " +fi - rm -rf $PREFIX-kvm*.qcow2 $PREFIX-xen.vhd *.mf *.ovf *.vmdk - sudo cp $TEMP_IMAGE_PATH/$PREFIX* $TEMP_IMAGE_PATH/metadata.ini $IMAGE_PATH - cd - - rm -rf $TEMP_IMAGE_PATH -fi \ No newline at end of file diff --git a/server/src/main/java/org/apache/cloudstack/ca/CAManagerImpl.java b/server/src/main/java/org/apache/cloudstack/ca/CAManagerImpl.java index 5f4a16e1fe57..2e7e756c49a8 100644 --- a/server/src/main/java/org/apache/cloudstack/ca/CAManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/ca/CAManagerImpl.java @@ -39,7 +39,6 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; -import com.google.common.base.Strings; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.command.admin.ca.IssueCertificateCmd; @@ -190,7 +189,7 @@ public boolean provisionCertificate(final Host host, final Boolean reconnect, fi try { if (host.getType() != Host.Type.ConsoleProxy && host.getType() != Host.Type.SecondaryStorageVM) { csr = generateKeyStoreAndCsr(host, null); - if (Strings.isNullOrEmpty(csr)) { + if (StringUtils.isEmpty(csr)) { return false; } } diff --git a/tools/appliance/build.sh b/tools/appliance/build.sh index 285d818c0c75..1c83f9aba510 100755 --- a/tools/appliance/build.sh +++ b/tools/appliance/build.sh @@ -348,11 +348,11 @@ function main() { packer_build # process the disk at dist -# kvm_export -# ovm_export -# xen_server_export + kvm_export + ovm_export + xen_server_export vmware_export -# hyperv_export + hyperv_export rm -f "dist/${appliance}" cd dist && chmod +r * && cd .. cd dist && md5sum * > md5sum.txt && cd .. From b07f20d5c659361af10b5a20f8b237761518ecad Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Thu, 20 Jan 2022 10:29:59 +0530 Subject: [PATCH 18/68] create vms folder in cloudstack-commons directory - debian rules --- debian/rules | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/rules b/debian/rules index e216fc77a7e0..0d5dfb21e482 100755 --- a/debian/rules +++ b/debian/rules @@ -116,6 +116,7 @@ override_dh_auto_install: mkdir $(DESTDIR)/usr/share/$(PACKAGE)-common/scripts mkdir $(DESTDIR)/usr/share/$(PACKAGE)-common/setup mkdir $(DESTDIR)/usr/share/$(PACKAGE)-common/lib + mkdir $(DESTDIR)/usr/share/$(PACKAGE)-common/vms cp -r scripts/installer $(DESTDIR)/usr/share/$(PACKAGE)-common/scripts cp -r scripts/network $(DESTDIR)/usr/share/$(PACKAGE)-common/scripts cp -r scripts/storage $(DESTDIR)/usr/share/$(PACKAGE)-common/scripts From 913726124b133846b6cf8ce5d07444308d2a27b4 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Fri, 21 Jan 2022 14:10:04 +0530 Subject: [PATCH 19/68] remove logic for on the fly template convert + update k8s test --- debian/control | 2 +- engine/schema/pom.xml | 52 +++++++++---------- .../upgrade/SystemVmTemplateRegistration.java | 18 ------- packaging/centos7/cloud.spec | 1 - packaging/centos8/cloud.spec | 1 - packaging/suse15/cloud.spec | 1 - .../systemd/cloudstack-management.service | 1 - .../smoke/test_kubernetes_clusters.py | 20 +++---- .../scripts/configure_systemvm_services.sh | 2 +- 9 files changed, 38 insertions(+), 60 deletions(-) diff --git a/debian/control b/debian/control index 06edfa3c5cac..066994785b38 100644 --- a/debian/control +++ b/debian/control @@ -15,7 +15,7 @@ Description: A common package which contains files which are shared by several C Package: cloudstack-management Architecture: all -Depends: ${python3:Depends}, openjdk-11-jre-headless | java11-runtime-headless | java11-runtime | openjdk-11-jre-headless | zulu-11, cloudstack-common (= ${source:Version}), net-tools, sudo, python3-mysql.connector, augeas-tools, mysql-client | mariadb-client, adduser, bzip2, ipmitool, file, gawk, iproute2, qemu-utils, python3-dnspython, lsb-release, init-system-helpers (>= 1.14~), python3-setuptools, libguestfs-tools +Depends: ${python3:Depends}, openjdk-11-jre-headless | java11-runtime-headless | java11-runtime | openjdk-11-jre-headless | zulu-11, cloudstack-common (= ${source:Version}), net-tools, sudo, python3-mysql.connector, augeas-tools, mysql-client | mariadb-client, adduser, bzip2, ipmitool, file, gawk, iproute2, qemu-utils, python3-dnspython, lsb-release, init-system-helpers (>= 1.14~), python3-setuptools Conflicts: cloud-server, cloud-client, cloud-client-ui Description: CloudStack server library The CloudStack management server diff --git a/engine/schema/pom.xml b/engine/schema/pom.xml index 1258289db98b..4cf0f4328d57 100644 --- a/engine/schema/pom.xml +++ b/engine/schema/pom.xml @@ -188,32 +188,32 @@ ${kvm.checksum} - - - - - - - - - - - - - - - - - - - - - - - - - - + + download-vmware-template + + wget + + + true + + http://10.0.3.122/systemvmtemplate/custom/cks-debian/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-vmware.ova + ${basedir}/dist/systemvm-templates/ + ${vmware.checksum} + + + + download-xenserver-template + + wget + + + true + + http://10.0.3.122/systemvmtemplate/custom/cks-debian/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-xen.vhd.bz2 + ${basedir}/dist/systemvm-templates/ + ${xen.checksum} + + diff --git a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java index 2df2de44995e..214243886997 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java @@ -93,7 +93,6 @@ public class SystemVmTemplateRegistration { public static final String TEMPORARY_SECONDARY_STORE = "tmp"; private static final String PARTIAL_TEMPLATE_FOLDER = String.format("/template/tmpl/%d/", Account.ACCOUNT_ID_SYSTEM); private static final String storageScriptsDir = "scripts/storage/secondary"; - private static final String installerScriptsDir = "scripts/installer/"; private static final Integer OTHER_LINUX_ID = 99; private static final Integer LINUX_5_ID = 15; private static final Integer LINUX_7_ID = 183; @@ -725,7 +724,6 @@ private void validateTemplates(Set hypervisorsInUse) } boolean templatesFound = true; - int count = hypervisors.size(); for (String hypervisor : hypervisors) { String matchedTemplate = templates.stream().filter(x -> x.contains(hypervisor)).findAny().orElse(null); if (matchedTemplate == null) { @@ -734,22 +732,6 @@ private void validateTemplates(Set hypervisorsInUse) } File tempFile = new File(TEMPLATES_PATH + matchedTemplate); - if (!tempFile.exists()) { - --count; - String exportTmpltScript = Script.findScript(installerScriptsDir, "export-templates.sh"); - if (exportTmpltScript == null) { - throw new CloudRuntimeException("Unable to find the export-templates.sh script to export templates on the fly"); - } - Script scr = new Script(exportTmpltScript, SCRIPT_TIMEOUT, LOGGER); - scr.add(hypervisor.toLowerCase(Locale.ROOT)); - scr.add((count > 0 ? "1" : "0")); - String result = scr.execute(); - if (result != null) { - String errMsg = String.format("failed to create template: %s ", result); - LOGGER.error(errMsg); - throw new CloudRuntimeException(errMsg); - } - } String templateChecksum = DigestHelper.calculateChecksum(tempFile); if (!templateChecksum.equals(NewTemplateChecksum.get(getHypervisorType(hypervisor)))) { LOGGER.error(String.format("Checksum mismatch: %s != %s ", templateChecksum, NewTemplateChecksum.get(getHypervisorType(hypervisor)))); diff --git a/packaging/centos7/cloud.spec b/packaging/centos7/cloud.spec index b2f77c5a83b2..81ee8a77a82f 100644 --- a/packaging/centos7/cloud.spec +++ b/packaging/centos7/cloud.spec @@ -79,7 +79,6 @@ Requires: /sbin/service Requires: /sbin/chkconfig Requires: /usr/bin/ssh-keygen Requires: genisoimage -Requires: libguestfs-tools Requires: ipmitool Requires: %{name}-common = %{_ver} Requires: iptables-services diff --git a/packaging/centos8/cloud.spec b/packaging/centos8/cloud.spec index 6a3627a57771..1a946ba0dd95 100644 --- a/packaging/centos8/cloud.spec +++ b/packaging/centos8/cloud.spec @@ -74,7 +74,6 @@ Requires: /sbin/service Requires: /sbin/chkconfig Requires: /usr/bin/ssh-keygen Requires: genisoimage -Requires: libguestfs-tools Requires: ipmitool Requires: %{name}-common = %{_ver} Requires: iptables-services diff --git a/packaging/suse15/cloud.spec b/packaging/suse15/cloud.spec index 77b6f6e95ac4..f355640c8650 100644 --- a/packaging/suse15/cloud.spec +++ b/packaging/suse15/cloud.spec @@ -75,7 +75,6 @@ Requires: /sbin/service Requires: /sbin/chkconfig Requires: /usr/bin/ssh-keygen Requires: mkisofs -Requires: libguestfs-tools Requires: ipmitool Requires: %{name}-common = %{_ver} Requires: qemu-tools diff --git a/packaging/systemd/cloudstack-management.service b/packaging/systemd/cloudstack-management.service index db94a42d6439..b979f7f375a7 100644 --- a/packaging/systemd/cloudstack-management.service +++ b/packaging/systemd/cloudstack-management.service @@ -35,7 +35,6 @@ EnvironmentFile=/etc/default/cloudstack-management WorkingDirectory=/var/log/cloudstack/management PIDFile=/var/run/cloudstack-management.pid ExecStart=/usr/bin/java $JAVA_DEBUG $JAVA_OPTS -cp $CLASSPATH $BOOTSTRAP_CLASS -TimeoutSec=900 [Install] WantedBy=multi-user.target diff --git a/test/integration/smoke/test_kubernetes_clusters.py b/test/integration/smoke/test_kubernetes_clusters.py index 0387ddf9cc1b..46f1f5d02bdc 100644 --- a/test/integration/smoke/test_kubernetes_clusters.py +++ b/test/integration/smoke/test_kubernetes_clusters.py @@ -101,12 +101,12 @@ def setUpClass(cls): (cls.services["cks_kubernetes_versions"]["1.20.9"]["semanticversion"], cls.services["cks_kubernetes_versions"]["1.20.9"]["url"], e)) if cls.setup_failed == False: try: - cls.kubernetes_version_1_21_3 = cls.addKubernetesSupportedVersion(cls.services["cks_kubernetes_versions"]["1.21.3"]) - cls.kubernetes_version_ids.append(cls.kubernetes_version_1_21_3.id) + cls.kubernetes_version_1_21_5 = cls.addKubernetesSupportedVersion(cls.services["cks_kubernetes_versions"]["1.21.5"]) + cls.kubernetes_version_ids.append(cls.kubernetes_version_1_21_5.id) except Exception as e: cls.setup_failed = True cls.debug("Failed to get Kubernetes version ISO in ready state, version=%s, url=%s, %s" % - (cls.services["cks_kubernetes_versions"]["1.21.3"]["semanticversion"], cls.services["cks_kubernetes_versions"]["1.21.3"]["url"], e)) + (cls.services["cks_kubernetes_versions"]["1.21.5"]["semanticversion"], cls.services["cks_kubernetes_versions"]["1.21.5"]["url"], e)) if cls.setup_failed == False: cks_offering_data = cls.services["cks_service_offering"] @@ -349,7 +349,7 @@ def test_01_invalid_upgrade_kubernetes_cluster(self): if self.setup_failed == True: self.fail("Setup incomplete") global k8s_cluster - k8s_cluster = self.getValidKubernetesCluster(version=self.kubernetes_version_1_21_3) + k8s_cluster = self.getValidKubernetesCluster(version=self.kubernetes_version_1_21_5) self.debug("Downgrading Kubernetes cluster with ID: %s to a lower version. This should fail!" % k8s_cluster.id) @@ -362,7 +362,7 @@ def test_01_invalid_upgrade_kubernetes_cluster(self): self.debug("Upgrading Kubernetes cluster with invalid Kubernetes supported version check successful, API failure: %s" % e) self.deleteKubernetesClusterAndVerify(k8s_cluster.id, False, True) - self.verifyKubernetesClusterUpgrade(k8s_cluster, self.kubernetes_version_1_21_3.id) + self.verifyKubernetesClusterUpgrade(k8s_cluster, self.kubernetes_version_1_21_5.id) return @attr(tags=["advanced", "smoke"], required_hardware="true") @@ -381,12 +381,12 @@ def test_02_upgrade_kubernetes_cluster(self): time.sleep(self.services["sleep"]) self.debug("Upgrading Kubernetes cluster with ID: %s" % k8s_cluster.id) try: - k8s_cluster = self.upgradeKubernetesCluster(k8s_cluster.id, self.kubernetes_version_1_21_3.id) + k8s_cluster = self.upgradeKubernetesCluster(k8s_cluster.id, self.kubernetes_version_1_21_5.id) except Exception as e: self.deleteKubernetesClusterAndVerify(k8s_cluster.id, False, True) self.fail("Failed to upgrade Kubernetes cluster due to: %s" % e) - self.verifyKubernetesClusterUpgrade(k8s_cluster, self.kubernetes_version_1_21_3.id) + self.verifyKubernetesClusterUpgrade(k8s_cluster, self.kubernetes_version_1_21_5.id) return @attr(tags=["advanced", "smoke"], required_hardware="true") @@ -434,7 +434,7 @@ def test_04_autoscale_kubernetes_cluster(self): if self.setup_failed == True: self.fail("Setup incomplete") global k8s_cluster - k8s_cluster = self.getValidKubernetesCluster(version=self.kubernetes_version_1_21_3) + k8s_cluster = self.getValidKubernetesCluster(version=self.kubernetes_version_1_21_5) self.debug("Autoscaling Kubernetes cluster with ID: %s" % k8s_cluster.id) try: @@ -535,12 +535,12 @@ def test_08_upgrade_kubernetes_ha_cluster(self): self.debug("Upgrading HA Kubernetes cluster with ID: %s" % k8s_cluster.id) try: - k8s_cluster = self.upgradeKubernetesCluster(k8s_cluster.id, self.kubernetes_version_1_21_3.id) + k8s_cluster = self.upgradeKubernetesCluster(k8s_cluster.id, self.kubernetes_version_1_21_5.id) except Exception as e: self.deleteKubernetesClusterAndVerify(k8s_cluster.id, False, True) self.fail("Failed to upgrade Kubernetes HA cluster due to: %s" % e) - self.verifyKubernetesClusterUpgrade(k8s_cluster, self.kubernetes_version_1_21_3.id) + self.verifyKubernetesClusterUpgrade(k8s_cluster, self.kubernetes_version_1_21_5.id) self.debug("Kubernetes cluster with ID: %s successfully upgraded" % k8s_cluster.id) return diff --git a/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh b/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh index 36b324a314f8..115d340fe846 100644 --- a/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh +++ b/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh @@ -19,7 +19,7 @@ set -e set -x -CLOUDSTACK_RELEASE=4.16.0 +CLOUDSTACK_RELEASE=4.17.0 function configure_apache2() { # Enable ssl, rewrite and auth From 554e7c81b4a8dcdc7d9c96c0cd4bb510025836ec Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Sat, 22 Jan 2022 12:51:30 +0530 Subject: [PATCH 20/68] fix syntax issue - causing issue with shared network tests --- systemvm/debian/opt/cloud/bin/setup/init.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/systemvm/debian/opt/cloud/bin/setup/init.sh b/systemvm/debian/opt/cloud/bin/setup/init.sh index 5923b351d1c2..a1ac48e46b56 100644 --- a/systemvm/debian/opt/cloud/bin/setup/init.sh +++ b/systemvm/debian/opt/cloud/bin/setup/init.sh @@ -190,7 +190,7 @@ setup_interface_sshd() { setup_common eth0 eth1 setup_sshd $ETH1_IP "eth1" - elif [ "$TYPE" == "elbvm" ] || [ "$TYPE" == "dhcpsrvr"]; then + elif [ "$TYPE" == "elbvm" ] || [ "$TYPE" == "dhcpsrvr" ]; then setup_common eth0 eth1 if [ "$SSHONGUEST" == "true" ]; then setup_sshd $ETH0_IP "eth0" From 9781668d7b77ae9a5d729bc1773dc9d065e2915a Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Thu, 27 Jan 2022 12:48:03 +0530 Subject: [PATCH 21/68] Code cleanup --- .../com/cloud/agent/api/StartCommand.java | 30 ------------------- .../VirtualRoutingResource.java | 22 ++++++++++++-- .../com/cloud/resource/ServerResource.java | 3 +- .../cloud/vm/VirtualMachineManagerImpl.java | 13 -------- .../LibvirtPatchSystemVmCommandWrapper.java | 2 +- .../wrapper/LibvirtStartCommandWrapper.java | 4 +-- .../vmware/resource/VmwareResource.java | 6 ++-- .../resource/CitrixResourceBase.java | 2 +- .../xenbase/CitrixStartCommandWrapper.java | 2 -- .../opt/cloud/bin/setup/cloud-early-config | 3 -- systemvm/patch-sysvms.sh | 3 +- 11 files changed, 26 insertions(+), 64 deletions(-) diff --git a/core/src/main/java/com/cloud/agent/api/StartCommand.java b/core/src/main/java/com/cloud/agent/api/StartCommand.java index 3af11932588e..24b0ac3787b5 100644 --- a/core/src/main/java/com/cloud/agent/api/StartCommand.java +++ b/core/src/main/java/com/cloud/agent/api/StartCommand.java @@ -29,12 +29,6 @@ public class StartCommand extends Command { String hostIp; boolean executeInSequence = false; String secondaryStorage; - @LogLevel(LogLevel.Log4jLevel.Off) - private String certificate; - @LogLevel(LogLevel.Log4jLevel.Off) - private String privateKey = ""; - @LogLevel(LogLevel.Log4jLevel.Off) - private String caCertificates; public VirtualMachineTO getVirtualMachine() { return vm; @@ -70,28 +64,4 @@ public String getSecondaryStorage() { public void setSecondaryStorage(String secondary) { this.secondaryStorage = secondary; } - - public void setCertificate(String certificate) { - this.certificate = certificate; - } - - public void setPrivateKey(String privateKey) { - this.privateKey = privateKey; - } - - public void setCaCertificates(String caCertificates) { - this.caCertificates = caCertificates; - } - - public String getCertificate() { - return certificate; - } - - public String getPrivateKey() { - return privateKey; - } - - public String getCaCertificates() { - return caCertificates; - } } diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java index cddee33ac382..ee85f3681f83 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java @@ -174,12 +174,28 @@ private Answer execute(final SetupKeyStoreCommand cmd) { return new SetupKeystoreAnswer(result.getDetails()); } + private void scpCertificateFiles(String routerIp, String path, String filename, String content) throws InterruptedException { + String errMsg = "Failed to scp file: %s to system VM"; + for (int retries = 5; retries > 0; retries--) { + try { + _vrDeployer.createFileInVR(routerIp, path, filename, content); + } catch (Exception e) { + errMsg += ", retrying"; + s_logger.error(String.format(errMsg, filename), e); + Thread.sleep(2000); + } + } + } private Answer execute(final SetupCertificateCommand cmd) { String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); if (!org.apache.commons.lang3.StringUtils.isEmpty(routerName) && (routerName.startsWith("s-") || routerName.startsWith("v-"))) { - _vrDeployer.createFileInVR(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.CERT_FILENAME, cmd.getCertificate()); - _vrDeployer.createFileInVR(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.CACERT_FILENAME, cmd.getCaCertificates()); - _vrDeployer.createFileInVR(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.PKEY_FILENAME, cmd.getPrivateKey()); + try { + scpCertificateFiles(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.CERT_FILENAME, cmd.getCertificate()); + scpCertificateFiles(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.CACERT_FILENAME, cmd.getCaCertificates()); + scpCertificateFiles(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.PKEY_FILENAME, cmd.getPrivateKey()); + } catch (InterruptedException e) { + throw new CloudRuntimeException(String.format("Failed to scp certificate file to %s due to %s", routerName, e.getLocalizedMessage())); + } } final String args = String.format("/usr/local/cloud/systemvm/conf/agent.properties %s " + "/usr/local/cloud/systemvm/conf/%s %s " + diff --git a/core/src/main/java/com/cloud/resource/ServerResource.java b/core/src/main/java/com/cloud/resource/ServerResource.java index f2beb4a1845a..0afb040b249f 100644 --- a/core/src/main/java/com/cloud/resource/ServerResource.java +++ b/core/src/main/java/com/cloud/resource/ServerResource.java @@ -35,8 +35,7 @@ */ public interface ServerResource extends Manager { - String[] srcFiles = new String[] { "agent.zip", "cloud-scripts.tgz" }; - String[] newSrcFiles = new String[] { "agent.zip", "cloud-scripts.tgz", "patch-sysvms.sh" }; + String[] systemVmPatchFiles = new String[] { "agent.zip", "cloud-scripts.tgz", "patch-sysvms.sh" }; String[] certificateFiles = new String[] {KeyStoreUtils.CERT_FILENAME, KeyStoreUtils.CACERT_FILENAME, KeyStoreUtils.PKEY_FILENAME}; String SSHKEYSPATH = "/root/.ssh"; diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index 0284d466234c..57992b7cc109 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -17,7 +17,6 @@ package com.cloud.vm; -import java.io.IOException; import java.net.URI; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -80,7 +79,6 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.cloudstack.utils.identity.ManagementServerNode; -import org.apache.cloudstack.utils.security.CertUtils; import org.apache.cloudstack.vm.UnmanagedVMsManager; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; @@ -1198,17 +1196,6 @@ public void orchestrateStart(final String vmUuid, final Map(ipAddressDetails.values()), CAManager.CertValidityPeriod.value(), null); - try { - command.setCertificate(CertUtils.x509CertificateToPem(certificate.getClientCertificate())); - command.setCaCertificates(CertUtils.x509CertificatesToPem(certificate.getCaCertificates())); - command.setPrivateKey(CertUtils.privateKeyToPem(certificate.getPrivateKey())); - } catch (IOException e) { - throw new CloudRuntimeException("Failed to generate/setup certificates for system VM"); - } - } cmds.addCommand(command); vmGuru.finalizeDeployment(cmds, vmProfile, dest, ctx); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java index 38b505f561ac..8d4700bf5694 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java @@ -70,7 +70,7 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR Pair patchResult = null; try { - FileUtil.scpPatchFiles(controlIp, "/home/cloud", sshPort, pemFile, serverResource.newSrcFiles, LibvirtComputingResource.BASEPATH); + FileUtil.scpPatchFiles(controlIp, "/home/cloud", sshPort, pemFile, serverResource.systemVmPatchFiles, LibvirtComputingResource.BASEPATH); patchResult = SshHelper.sshExecute(controlIp, sshPort, "root", pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 600000); } catch (Exception e) { diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java index 1f6a0256cc83..b8c2e447ae2a 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java @@ -120,9 +120,7 @@ public Answer execute(final StartCommand command, final LibvirtComputingResource try { File pemFile = new File(LibvirtComputingResource.SSHPRVKEYPATH); - FileUtil.scpPatchFiles(controlIp, "/home/cloud", Integer.parseInt(LibvirtComputingResource.DEFAULTDOMRSSHPORT), pemFile, LibvirtComputingResource.newSrcFiles, LibvirtComputingResource.BASEPATH); - // TODO: May want to remove this when cert patching logic is moved - Thread.sleep(10000); + FileUtil.scpPatchFiles(controlIp, "/home/cloud", Integer.parseInt(LibvirtComputingResource.DEFAULTDOMRSSHPORT), pemFile, LibvirtComputingResource.systemVmPatchFiles, LibvirtComputingResource.BASEPATH); } catch (Exception e) { String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; s_logger.error(errMsg, e); diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 476734284749..6891bfd19320 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -662,7 +662,7 @@ private Answer execute(PatchSystemVmCommand cmd) { ExecutionResult result = getSystemVmVersionAndChecksum(controlIp); try { - FileUtil.scpPatchFiles(controlIp, "/home/cloud", DefaultDomRSshPort, pemFile, newSrcFiles, BASEPATH); + FileUtil.scpPatchFiles(controlIp, "/home/cloud", DefaultDomRSshPort, pemFile, systemVmPatchFiles, BASEPATH); } catch (CloudRuntimeException e) { return new PatchSystemVmAnswer(cmd, e.getMessage()); } @@ -2549,9 +2549,7 @@ protected StartAnswer execute(StartCommand cmd) { try { String homeDir = System.getProperty("user.home"); File pemFile = new File(homeDir + "/.ssh/id_rsa"); - FileUtil.scpPatchFiles(controlIp, "/home/cloud", DefaultDomRSshPort, pemFile, newSrcFiles, BASEPATH); - // TODO: May want to remove this when cert patching logic is moved - Thread.sleep(10000); + FileUtil.scpPatchFiles(controlIp, "/home/cloud", DefaultDomRSshPort, pemFile, systemVmPatchFiles, BASEPATH); } catch (Exception e) { String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; s_logger.error(errMsg, e); diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java index 010fad4c1e93..ee45ffbd8bb6 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java @@ -996,7 +996,7 @@ public ExecutionResult copyPatchFilesToVR(final String routerIp, final String pa final Connection conn = getConnection(); final String hostPath = "/opt/xensource/packages/resources/"; String rc = ""; - for (String file: newSrcFiles) { + for (String file: systemVmPatchFiles) { rc = callHostPlugin(conn, "vmops", "createFileInDomr", "domrip", routerIp, "srcfilepath", hostPath.concat(file), "dstfilepath", path, "cleanup", "false"); if (rc.startsWith("fail#")) { s_logger.error(String.format("Failed to scp file %s required for patching the systemVM", file)); diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java index f4ee77c347f3..73a74f89d5dd 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java @@ -196,8 +196,6 @@ public Answer execute(final StartCommand command, final CitrixResourceBase citri try { citrixResourceBase.copyPatchFilesToVR(controlIp, "/home/cloud"); - // TODO: May want to remove this when cert patching logic is moved - Thread.sleep(10000); } catch (Exception e) { String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; s_logger.error(errMsg, e); diff --git a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config index 13fa9987a5e7..1227c68850b9 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config +++ b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config @@ -100,9 +100,6 @@ patch() { cleanup() { rm -rf /home/cloud/agent.zip mv /home/cloud/cloud-scripts.tgz /usr/share/cloud/cloud-scripts.tgz - if [ -f /home/cloud/cloud.crt ]; then - mv /home/cloud/cloud.crt /home/cloud/cloud.ca.crt /home/cloud/cloud.key /usr/local/cloud/systemvm/conf/ - fi } start() { diff --git a/systemvm/patch-sysvms.sh b/systemvm/patch-sysvms.sh index 148c8a80b9da..4a6873147b8f 100644 --- a/systemvm/patch-sysvms.sh +++ b/systemvm/patch-sysvms.sh @@ -74,7 +74,6 @@ restart_services() { systemctl is-active --quiet "$svc" if [ $? -eq 0 ]; then systemctl restart "$svc" - sleep 5 systemctl is-active --quiet "$svc" if [ $? -gt 0 ]; then echo "Failed to start "$svc" service. Patch Failed. Retrying again" >> $logfile 2>&1 @@ -100,10 +99,10 @@ cleanup_systemVM() { patch_systemvm() { rm -rf /usr/local/cloud/systemvm - mkdir -p /usr/local/cloud/systemvm if [ "$TYPE" == "consoleproxy" ] || [ "$TYPE" == "secstorage" ]; then echo "All" | unzip $newpath/agent.zip -d /usr/local/cloud/systemvm >> $logfile 2>&1 + mkdir -p /usr/local/cloud/systemvm find /usr/local/cloud/systemvm/ -name \*.sh | xargs chmod 555 fi echo "Extracting cloud scripts" >> $logfile 2>&1 From 6244ca434cab8695906d7e45cf21be9a01c9c689 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Tue, 1 Feb 2022 10:42:59 +0530 Subject: [PATCH 22/68] refactor patching logic - certs --- .../VirtualRoutingResource.java | 66 ++++----- .../upgrade/SystemVmTemplateRegistration.java | 5 +- .../resource/LibvirtComputingResource.java | 136 +++++++++--------- scripts/util/keystore-cert-import | 1 + .../cloud/server/ConfigurationServerImpl.java | 1 - 5 files changed, 100 insertions(+), 109 deletions(-) diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java index ee85f3681f83..6ae27cc6500a 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java @@ -19,36 +19,6 @@ package com.cloud.agent.resource.virtualnetwork; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.nio.channels.SocketChannel; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.UUID; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import javax.naming.ConfigurationException; - -import com.cloud.utils.PasswordGenerator; -import org.apache.cloudstack.ca.SetupCertificateAnswer; -import org.apache.cloudstack.ca.SetupCertificateCommand; -import org.apache.cloudstack.ca.SetupKeyStoreCommand; -import org.apache.cloudstack.ca.SetupKeystoreAnswer; -import org.apache.cloudstack.diagnostics.DeleteFileInVrCommand; -import org.apache.cloudstack.diagnostics.DiagnosticsAnswer; -import org.apache.cloudstack.diagnostics.DiagnosticsCommand; -import org.apache.cloudstack.diagnostics.PrepareFilesAnswer; -import org.apache.cloudstack.diagnostics.PrepareFilesCommand; -import org.apache.cloudstack.utils.security.KeyStoreUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; -import org.joda.time.Duration; - import com.cloud.agent.api.Answer; import com.cloud.agent.api.CheckRouterAnswer; import com.cloud.agent.api.CheckRouterCommand; @@ -68,7 +38,35 @@ import com.cloud.utils.ExecutionResult; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; +import com.cloud.utils.PasswordGenerator; import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.cloudstack.ca.SetupCertificateAnswer; +import org.apache.cloudstack.ca.SetupCertificateCommand; +import org.apache.cloudstack.ca.SetupKeyStoreCommand; +import org.apache.cloudstack.ca.SetupKeystoreAnswer; +import org.apache.cloudstack.diagnostics.DeleteFileInVrCommand; +import org.apache.cloudstack.diagnostics.DiagnosticsAnswer; +import org.apache.cloudstack.diagnostics.DiagnosticsCommand; +import org.apache.cloudstack.diagnostics.PrepareFilesAnswer; +import org.apache.cloudstack.diagnostics.PrepareFilesCommand; +import org.apache.cloudstack.utils.security.KeyStoreUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Logger; +import org.joda.time.Duration; + +import javax.naming.ConfigurationException; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.channels.SocketChannel; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.UUID; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; /** * VirtualNetworkResource controls and configures virtual networking @@ -174,9 +172,9 @@ private Answer execute(final SetupKeyStoreCommand cmd) { return new SetupKeystoreAnswer(result.getDetails()); } - private void scpCertificateFiles(String routerIp, String path, String filename, String content) throws InterruptedException { + private void scpFileToIdentifyPatching(String routerIp, String path, String filename, String content) throws InterruptedException { String errMsg = "Failed to scp file: %s to system VM"; - for (int retries = 5; retries > 0; retries--) { + for (int retries = 15; retries > 0; retries--) { try { _vrDeployer.createFileInVR(routerIp, path, filename, content); } catch (Exception e) { @@ -190,9 +188,7 @@ private Answer execute(final SetupCertificateCommand cmd) { String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); if (!org.apache.commons.lang3.StringUtils.isEmpty(routerName) && (routerName.startsWith("s-") || routerName.startsWith("v-"))) { try { - scpCertificateFiles(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.CERT_FILENAME, cmd.getCertificate()); - scpCertificateFiles(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.CACERT_FILENAME, cmd.getCaCertificates()); - scpCertificateFiles(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.PKEY_FILENAME, cmd.getPrivateKey()); + scpFileToIdentifyPatching(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.CERT_FILENAME, cmd.getCertificate()); } catch (InterruptedException e) { throw new CloudRuntimeException(String.format("Failed to scp certificate file to %s due to %s", routerName, e.getLocalizedMessage())); } diff --git a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java index 214243886997..78afe3a45c02 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java @@ -470,7 +470,7 @@ private VMTemplateVO createTemplateObjectInDB(SystemVMTemplateDetails details) { template.setCrossZones(true); template.setHypervisorType(details.getHypervisorType()); template.setState(VirtualMachineTemplate.State.Inactive); - template.setDeployAsIs(Hypervisor.HypervisorType.VMware.equals(details.getHypervisorType())); + template.setDeployAsIs(false); template = vmTemplateDao.persist(template); return template; } @@ -828,9 +828,6 @@ private void updateRegisteredTemplateDetails(Long templateId, Map.Entry hypervisorAndTemplateName) { templateVO.setUrl(NewTemplateUrl.get(hypervisorAndTemplateName.getKey())); templateVO.setChecksum(NewTemplateChecksum.get(hypervisorAndTemplateName.getKey())); - if (Hypervisor.HypervisorType.VMware == templateVO.getHypervisorType()) { - templateVO.setDeployAsIs(true); - } boolean updated = vmTemplateDao.update(templateVO.getId(), templateVO); if (!updated) { String errMsg = String.format("updateSystemVmTemplates:Exception while updating 'url' and 'checksum' for hypervisor type %s", hypervisorAndTemplateName.getKey().name()); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 99296e2e40fd..b2b7050bb8fc 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -16,74 +16,6 @@ // under the License. package com.cloud.hypervisor.kvm.resource; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.StringReader; -import java.net.InetAddress; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.naming.ConfigurationException; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -import com.cloud.configuration.Config; -import org.apache.cloudstack.storage.configdrive.ConfigDrive; -import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; -import org.apache.cloudstack.storage.to.TemplateObjectTO; -import org.apache.cloudstack.storage.to.VolumeObjectTO; -import org.apache.cloudstack.utils.hypervisor.HypervisorUtils; -import org.apache.cloudstack.utils.linux.CPUStat; -import org.apache.cloudstack.utils.linux.KVMHostInfo; -import org.apache.cloudstack.utils.linux.MemStat; -import org.apache.cloudstack.utils.qemu.QemuImg; -import org.apache.cloudstack.utils.qemu.QemuImgException; -import org.apache.cloudstack.utils.qemu.QemuImgFile; -import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; -import org.apache.cloudstack.utils.security.KeyStoreUtils; -import org.apache.commons.collections.MapUtils; -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.ArrayUtils; -import org.apache.commons.lang.BooleanUtils; -import org.apache.commons.lang.math.NumberUtils; -import org.apache.log4j.Logger; -import org.joda.time.Duration; -import org.libvirt.Connect; -import org.libvirt.Domain; -import org.libvirt.DomainBlockStats; -import org.libvirt.DomainInfo; -import org.libvirt.DomainInfo.DomainState; -import org.libvirt.DomainInterfaceStats; -import org.libvirt.DomainSnapshot; -import org.libvirt.LibvirtException; -import org.libvirt.MemoryStatistic; -import org.libvirt.Network; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.HostVmStateReportEntry; @@ -115,6 +47,7 @@ import com.cloud.agent.resource.virtualnetwork.VRScripts; import com.cloud.agent.resource.virtualnetwork.VirtualRouterDeployer; import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource; +import com.cloud.configuration.Config; import com.cloud.dc.Vlan; import com.cloud.exception.InternalErrorException; import com.cloud.host.Host.Type; @@ -184,9 +117,74 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.PowerState; import com.cloud.vm.VmDetailConstants; -import org.apache.commons.lang3.StringUtils; +import org.apache.cloudstack.storage.configdrive.ConfigDrive; +import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; +import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.cloudstack.utils.bytescale.ByteScaleUtils; +import org.apache.cloudstack.utils.hypervisor.HypervisorUtils; +import org.apache.cloudstack.utils.linux.CPUStat; +import org.apache.cloudstack.utils.linux.KVMHostInfo; +import org.apache.cloudstack.utils.linux.MemStat; +import org.apache.cloudstack.utils.qemu.QemuImg; +import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; +import org.apache.cloudstack.utils.qemu.QemuImgException; +import org.apache.cloudstack.utils.qemu.QemuImgFile; +import org.apache.cloudstack.utils.security.KeyStoreUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.BooleanUtils; +import org.apache.commons.lang.math.NumberUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Logger; +import org.joda.time.Duration; +import org.libvirt.Connect; +import org.libvirt.Domain; +import org.libvirt.DomainBlockStats; +import org.libvirt.DomainInfo; +import org.libvirt.DomainInfo.DomainState; +import org.libvirt.DomainInterfaceStats; +import org.libvirt.DomainSnapshot; +import org.libvirt.LibvirtException; +import org.libvirt.MemoryStatistic; +import org.libvirt.Network; import org.libvirt.VcpuInfo; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import javax.naming.ConfigurationException; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.StringReader; +import java.net.InetAddress; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * LibvirtComputingResource execute requests on the computing/routing host using diff --git a/scripts/util/keystore-cert-import b/scripts/util/keystore-cert-import index 0a112e9303e8..64ae92bcfdc3 100755 --- a/scripts/util/keystore-cert-import +++ b/scripts/util/keystore-cert-import @@ -33,6 +33,7 @@ LIBVIRTD_FILE="/etc/libvirt/libvirtd.conf" if [ ! -f "$LIBVIRTD_FILE" ]; then # Re-use existing password or use the one provided + while [ ! -d /usr/local/cloud/systemvm/conf ]; do sleep 1; done if [ -f "$PROPS_FILE" ]; then OLD_PASS=$(sed -n '/keystore.passphrase/p' "$PROPS_FILE" 2>/dev/null | sed 's/keystore.passphrase=//g' 2>/dev/null) if [ ! -z "${OLD_PASS// }" ]; then diff --git a/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java b/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java index f6e4d517ea84..64d353dd0414 100644 --- a/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java @@ -667,7 +667,6 @@ public void doInTransactionWithoutResult(TransactionStatus status) { s_logger.info("Keypairs already in database, updating local copy"); updateKeyPairsOnDisk(homeDir); } - s_logger.info("Going to update systemvm iso with generated keypairs if needed"); try { copyPrivateKeyToHosts(pubkeyfile.getAbsolutePath(), privkeyfile.getAbsolutePath()); } catch (CloudRuntimeException e) { From 0196929eb9ae199210cdebf1967336e387844737 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Tue, 1 Feb 2022 13:52:49 +0530 Subject: [PATCH 23/68] move logic of fixing rootdiskcontroller from upgrade to kubernetes service --- .../wrapper/LibvirtStartCommandWrapper.java | 20 ++++---- .../vmware/resource/VmwareResource.java | 1 + .../xenbase/CitrixStartCommandWrapper.java | 18 ++++---- ...esClusterResourceModifierActionWorker.java | 46 ++++++++++--------- .../KubernetesClusterStartWorker.java | 42 +++++++++-------- 5 files changed, 68 insertions(+), 59 deletions(-) diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java index b8c2e447ae2a..f944475ac332 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java @@ -19,15 +19,6 @@ package com.cloud.hypervisor.kvm.resource.wrapper; -import java.io.File; -import java.net.URISyntaxException; - -import com.cloud.utils.FileUtil; -import org.apache.log4j.Logger; -import org.libvirt.Connect; -import org.libvirt.DomainInfo.DomainState; -import org.libvirt.LibvirtException; - import com.cloud.agent.api.Answer; import com.cloud.agent.api.StartAnswer; import com.cloud.agent.api.StartCommand; @@ -36,14 +27,22 @@ import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource; import com.cloud.exception.InternalErrorException; import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource; -import com.cloud.hypervisor.kvm.resource.LibvirtVMDef; import com.cloud.hypervisor.kvm.resource.LibvirtKvmAgentHook; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef; import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager; import com.cloud.network.Networks.TrafficType; import com.cloud.resource.CommandWrapper; import com.cloud.resource.ResourceWrapper; +import com.cloud.utils.FileUtil; import com.cloud.vm.UserVmManager; import com.cloud.vm.VirtualMachine; +import org.apache.log4j.Logger; +import org.libvirt.Connect; +import org.libvirt.DomainInfo.DomainState; +import org.libvirt.LibvirtException; + +import java.io.File; +import java.net.URISyntaxException; @ResourceWrapper(handles = StartCommand.class) public final class LibvirtStartCommandWrapper extends CommandWrapper { @@ -121,6 +120,7 @@ public Answer execute(final StartCommand command, final LibvirtComputingResource try { File pemFile = new File(LibvirtComputingResource.SSHPRVKEYPATH); FileUtil.scpPatchFiles(controlIp, "/home/cloud", Integer.parseInt(LibvirtComputingResource.DEFAULTDOMRSSHPORT), pemFile, LibvirtComputingResource.systemVmPatchFiles, LibvirtComputingResource.BASEPATH); + Thread.sleep(10000); } catch (Exception e) { String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; s_logger.error(errMsg, e); diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 6891bfd19320..8a7ca33fef68 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -2550,6 +2550,7 @@ protected StartAnswer execute(StartCommand cmd) { String homeDir = System.getProperty("user.home"); File pemFile = new File(homeDir + "/.ssh/id_rsa"); FileUtil.scpPatchFiles(controlIp, "/home/cloud", DefaultDomRSshPort, pemFile, systemVmPatchFiles, BASEPATH); + Thread.sleep(10000); } catch (Exception e) { String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; s_logger.error(errMsg, e); diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java index 73a74f89d5dd..7f379404548b 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java @@ -19,15 +19,6 @@ package com.cloud.hypervisor.xenserver.resource.wrapper.xenbase; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; - import com.cloud.agent.api.Answer; import com.cloud.agent.api.OvsSetTagAndFlowAnswer; import com.cloud.agent.api.OvsSetTagAndFlowCommand; @@ -51,6 +42,14 @@ import com.xensource.xenapi.Types.VmPowerState; import com.xensource.xenapi.VDI; import com.xensource.xenapi.VM; +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Logger; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; @ResourceWrapper(handles = StartCommand.class) public final class CitrixStartCommandWrapper extends CommandWrapper { @@ -196,6 +195,7 @@ public Answer execute(final StartCommand command, final CitrixResourceBase citri try { citrixResourceBase.copyPatchFilesToVR(controlIp, "/home/cloud"); + Thread.sleep(10000); } catch (Exception e) { String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; s_logger.error(errMsg, e); diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java index 98e4587dff37..560774471e55 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java @@ -17,27 +17,6 @@ package com.cloud.kubernetes.cluster.actionworkers; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import javax.inject.Inject; - -import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.BaseCmd; -import org.apache.cloudstack.api.command.user.firewall.CreateFirewallRuleCmd; -import org.apache.cloudstack.api.command.user.vm.StartVMCmd; -import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Level; - import com.cloud.capacity.CapacityManager; import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.ClusterDetailsVO; @@ -75,9 +54,9 @@ import com.cloud.offering.ServiceOffering; import com.cloud.resource.ResourceManager; import com.cloud.storage.Volume; +import com.cloud.storage.VolumeApiService; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.LaunchPermissionDao; -import com.cloud.storage.VolumeApiService; import com.cloud.storage.dao.VolumeDao; import com.cloud.user.Account; import com.cloud.user.SSHKeyPairVO; @@ -95,7 +74,27 @@ import com.cloud.vm.Nic; import com.cloud.vm.UserVmManager; import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VmDetailConstants; import com.cloud.vm.dao.VMInstanceDao; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.command.user.firewall.CreateFirewallRuleCmd; +import org.apache.cloudstack.api.command.user.vm.StartVMCmd; +import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Level; + +import javax.inject.Inject; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import static com.cloud.utils.NumbersUtil.toHumanReadableSize; @@ -362,6 +361,9 @@ protected UserVm createKubernetesNode(String joinIp) throws ManagementServerExce if (rootDiskSize > 0) { customParameterMap.put("rootdisksize", String.valueOf(rootDiskSize)); } + if (Hypervisor.HypervisorType.VMware.equals(clusterTemplate.getHypervisorType())) { + customParameterMap.put(VmDetailConstants.ROOT_DISK_CONTROLLER, "scsi"); + } String suffix = Long.toHexString(System.currentTimeMillis()); String hostName = String.format("%s-node-%s", kubernetesClusterNodeNamePrefix, suffix); String k8sNodeConfig = null; diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java index e2496a04c25b..b64179fb5829 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java @@ -17,24 +17,6 @@ package com.cloud.kubernetes.cluster.actionworkers; -import java.io.IOException; -import java.net.InetAddress; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.cloudstack.api.BaseCmd; -import org.apache.cloudstack.framework.ca.Certificate; -import org.apache.cloudstack.utils.security.CertUtils; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.collections.CollectionUtils; -import org.apache.log4j.Level; - import com.cloud.dc.DataCenter; import com.cloud.dc.Vlan; import com.cloud.dc.VlanVO; @@ -73,7 +55,25 @@ import com.cloud.vm.ReservationContextImpl; import com.cloud.vm.UserVmManager; import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VmDetailConstants; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.framework.ca.Certificate; +import org.apache.cloudstack.utils.security.CertUtils; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Level; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class KubernetesClusterStartWorker extends KubernetesClusterResourceModifierActionWorker { @@ -197,6 +197,9 @@ private UserVm createKubernetesControlNode(final Network network, String serverI if (rootDiskSize > 0) { customParameterMap.put("rootdisksize", String.valueOf(rootDiskSize)); } + if (Hypervisor.HypervisorType.VMware.equals(clusterTemplate.getHypervisorType())) { + customParameterMap.put(VmDetailConstants.ROOT_DISK_CONTROLLER, "scsi"); + } String suffix = Long.toHexString(System.currentTimeMillis()); String hostName = String.format("%s-control-%s", kubernetesClusterNodeNamePrefix, suffix); boolean haSupported = isKubernetesVersionSupportsHA(); @@ -254,6 +257,9 @@ private UserVm createKubernetesAdditionalControlNode(final String joinIp, final if (rootDiskSize > 0) { customParameterMap.put("rootdisksize", String.valueOf(rootDiskSize)); } + if (Hypervisor.HypervisorType.VMware.equals(clusterTemplate.getHypervisorType())) { + customParameterMap.put(VmDetailConstants.ROOT_DISK_CONTROLLER, "scsi"); + } String suffix = Long.toHexString(System.currentTimeMillis()); String hostName = String.format("%s-control-%s", kubernetesClusterNodeNamePrefix, suffix); String k8sControlNodeConfig = null; From 21f0cf5a36af350eb726e34be8f86b003ffeb9b9 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Wed, 2 Feb 2022 12:25:26 +0530 Subject: [PATCH 24/68] add livepatch option to restart network & vpc --- ui/src/config/section/network.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ui/src/config/section/network.js b/ui/src/config/section/network.js index 5928c6eee24b..d6193928c982 100644 --- a/ui/src/config/section/network.js +++ b/ui/src/config/section/network.js @@ -99,7 +99,14 @@ export default { label: 'label.restart.network', message: 'message.restart.network', dataView: true, - args: ['cleanup', 'livepatch'], + args: (record) => { + var fields = [] + if (record.vpcid == null) { + fields.push('cleanup') + } + fields.push('livepatch') + return fields + }, show: (record) => record.type !== 'L2', groupAction: true, popup: true, @@ -191,6 +198,7 @@ export default { if (!record.redundantvpcrouter) { fields.push('makeredundant') } + fields.push('livepatch') return fields }, groupAction: true, From 92c71c01c31631cf27f1918203a1da5dec1e9a21 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Wed, 2 Feb 2022 12:21:16 +0530 Subject: [PATCH 25/68] smooth upgrade of cks clusters --- .../java/com/cloud/vm/VmDetailConstants.java | 1 + .../META-INF/db/schema-41600to41610.sql | 20 +++++++ .../KubernetesClusterActionWorker.java | 58 +++++++++++++++++-- ...esClusterResourceModifierActionWorker.java | 7 ++- .../KubernetesClusterScaleWorker.java | 8 ++- .../KubernetesClusterStartWorker.java | 11 ++-- .../KubernetesClusterUpgradeWorker.java | 10 ++-- 7 files changed, 94 insertions(+), 21 deletions(-) diff --git a/api/src/main/java/com/cloud/vm/VmDetailConstants.java b/api/src/main/java/com/cloud/vm/VmDetailConstants.java index bf43940c0a02..5fbbc872d341 100644 --- a/api/src/main/java/com/cloud/vm/VmDetailConstants.java +++ b/api/src/main/java/com/cloud/vm/VmDetailConstants.java @@ -73,4 +73,5 @@ public interface VmDetailConstants { String DISK_OFFERING = "diskOffering"; String DEPLOY_AS_IS_CONFIGURATION = "configurationId"; + String CKS_CONTROL_NODE_LOGIN_USER = "controlNodeLoginUser"; } diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41600to41610.sql b/engine/schema/src/main/resources/META-INF/db/schema-41600to41610.sql index 979d87d461e7..eac0729f3bdb 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-41600to41610.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-41600to41610.sql @@ -130,3 +130,23 @@ CALL `cloud_usage`.`IDEMPOTENT_ADD_COLUMN`('cloud_usage.usage_vpn_user', 'id', ' UPDATE `cloud`.`vm_template` set deploy_as_is = 0 where id = 8; +CREATE PROCEDURE `cloud`.`UPDATE_KUBERNETES_NODE_DETAILS`() +BEGIN + DECLARE vmid BIGINT +; DECLARE done TINYINT DEFAULT FALSE +; DECLARE vmidcursor CURSOR FOR SELECT DISTINCT(vm_id) FROM `cloud`.`kubernetes_cluster_vm_map` +; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE +; OPEN vmidcursor +; vmid_loop:LOOP + FETCH NEXT FROM vmidcursor INTO vmid +; IF done THEN + LEAVE vmid_loop +; ELSE + INSERT `cloud`.`user_vm_details` (vm_id, name, value, display) VALUES (vmid, 'controlNodeLoginUser', 'core', 1) +; END IF +; END LOOP +; CLOSE vmidcursor +; END; + +CALL `cloud`.`UPDATE_KUBERNETES_NODE_DETAILS`(); +DROP PROCEDURE IF EXISTS `cloud`.`UPDATE_KUBERNETES_NODE_DETAILS`; diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java index eaf00f30a80e..8f32c15c85f5 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java @@ -23,11 +23,15 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; import javax.inject.Inject; +import com.cloud.vm.dao.UserVmDetailsDao; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.ca.CAManager; import org.apache.cloudstack.config.ApiServiceConfiguration; @@ -78,10 +82,14 @@ import com.cloud.utils.fsm.NoTransitionException; import com.cloud.utils.fsm.StateMachine2; import com.cloud.utils.ssh.SshHelper; +import com.cloud.vm.UserVmDetailVO; import com.cloud.vm.UserVmService; +import com.cloud.vm.UserVmVO; import com.cloud.vm.VirtualMachineManager; +import com.cloud.vm.VmDetailConstants; import com.cloud.vm.dao.UserVmDao; + public class KubernetesClusterActionWorker { public static final String CLUSTER_NODE_VM_USER = "cloud"; @@ -119,6 +127,8 @@ public class KubernetesClusterActionWorker { @Inject protected UserVmDao userVmDao; @Inject + protected UserVmDetailsDao userVmDetailsDao; + @Inject protected UserVmService userVmService; @Inject protected VlanDao vlanDao; @@ -174,6 +184,27 @@ protected String readResourceFile(String resource) throws IOException { return IOUtils.toString(Objects.requireNonNull(Thread.currentThread().getContextClassLoader().getResourceAsStream(resource)), com.cloud.utils.StringUtils.getPreferredCharset()); } + protected String getControlNodeLoginUser() { + List vmMapVOList = getKubernetesClusterVMMaps(); + if (vmMapVOList.size() > 0) { + long vmId = vmMapVOList.get(0).getVmId(); + UserVmVO userVM = userVmDao.findById(vmId); + if (userVM == null) { + throw new CloudRuntimeException("Failed to find login user, Unable to log in to node to fetch details"); + } + Set vm = new HashSet<>(); + vm.add(userVM.getName()); + UserVmDetailVO vmDetail = userVmDetailsDao.findDetail(vmId, VmDetailConstants.CKS_CONTROL_NODE_LOGIN_USER); + if (vmDetail != null && !org.apache.commons.lang3.StringUtils.isEmpty(vmDetail.getValue())) { + return vmDetail.getValue(); + } else { + return CLUSTER_NODE_VM_USER; + } + } else { + return CLUSTER_NODE_VM_USER; + } + } + protected void logMessage(final Level logLevel, final String message, final Exception e) { if (logLevel == Level.INFO) { if (LOGGER.isInfoEnabled()) { @@ -409,6 +440,20 @@ protected List getKubernetesClusterVMs() { return vmList; } + protected void updateLoginUserDetails(List clusterVMs) { + if (clusterVMs == null) { + clusterVMs = getKubernetesClusterVMMaps().stream().map(KubernetesClusterVmMapVO::getVmId).collect(Collectors.toList()); + } + if (!CollectionUtils.isEmpty(clusterVMs)) { + for (Long vmId : clusterVMs) { + UserVm controlNode = userVmDao.findById(vmId); + if (controlNode != null) { + userVmDetailsDao.addDetail(vmId, VmDetailConstants.CKS_CONTROL_NODE_LOGIN_USER, CLUSTER_NODE_VM_USER, true); + } + } + } + } + protected boolean stateTransitTo(long kubernetesClusterId, KubernetesCluster.Event e) { KubernetesClusterVO kubernetesCluster = kubernetesClusterDao.findById(kubernetesClusterId); try { @@ -423,13 +468,14 @@ protected boolean stateTransitTo(long kubernetesClusterId, KubernetesCluster.Eve protected boolean createCloudStackSecret(String[] keys) { File pkFile = getManagementServerSshPublicKeyFile(); Pair publicIpSshPort = getKubernetesClusterServerIpSshPort(null); + List vmMapVOList = getKubernetesClusterVMMaps(); publicIpAddress = publicIpSshPort.first(); sshPort = publicIpSshPort.second(); try { final String command = String.format("sudo %s/%s -u '%s' -k '%s' -s '%s'", scriptPath, deploySecretsScriptFilename, ApiServiceConfiguration.ApiServletPath.value(), keys[0], keys[1]); - Pair result = SshHelper.sshExecute(publicIpAddress, sshPort, CLUSTER_NODE_VM_USER, + Pair result = SshHelper.sshExecute(publicIpAddress, sshPort, getControlNodeLoginUser(), pkFile, null, command, 10000, 10000, 60000); return result.first(); } catch (Exception e) { @@ -468,10 +514,10 @@ protected void copyScripts(String nodeAddress, final int sshPort) { protected void copyScriptFile(String nodeAddress, final int sshPort, File file, String desitnation) { try { - SshHelper.scpTo(nodeAddress, sshPort, CLUSTER_NODE_VM_USER, sshKeyFile, null, + SshHelper.scpTo(nodeAddress, sshPort, getControlNodeLoginUser(), sshKeyFile, null, "~/", file.getAbsolutePath(), "0755"); String cmdStr = String.format("sudo mv ~/%s %s/%s", file.getName(), scriptPath, desitnation); - SshHelper.sshExecute(publicIpAddress, sshPort, CLUSTER_NODE_VM_USER, sshKeyFile, null, + SshHelper.sshExecute(publicIpAddress, sshPort, getControlNodeLoginUser(), sshKeyFile, null, cmdStr, 10000, 10000, 10 * 60 * 1000); } catch (Exception e) { throw new CloudRuntimeException(e); @@ -495,7 +541,7 @@ protected boolean taintControlNodes() { publicIpAddress = publicIpSshPort.first(); sshPort = publicIpSshPort.second(); - Pair result = SshHelper.sshExecute(publicIpAddress, sshPort, CLUSTER_NODE_VM_USER, + Pair result = SshHelper.sshExecute(publicIpAddress, sshPort, getControlNodeLoginUser(), pkFile, null, commands.toString(), 10000, 10000, 60000); return result.first(); } catch (Exception e) { @@ -520,7 +566,7 @@ protected boolean deployProvider() { try { String command = String.format("sudo %s/%s", scriptPath, deployProviderScriptFilename); - Pair result = SshHelper.sshExecute(publicIpAddress, sshPort, CLUSTER_NODE_VM_USER, + Pair result = SshHelper.sshExecute(publicIpAddress, sshPort, getControlNodeLoginUser(), pkFile, null, command, 10000, 10000, 60000); // Maybe the file isn't present. Try and copy it @@ -535,7 +581,7 @@ protected boolean deployProvider() { } // If at first you don't succeed ... - result = SshHelper.sshExecute(publicIpAddress, sshPort, CLUSTER_NODE_VM_USER, + result = SshHelper.sshExecute(publicIpAddress, sshPort, getControlNodeLoginUser(), pkFile, null, command, 10000, 10000, 60000); if (!result.first()) { throw new CloudRuntimeException(result.second()); diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java index 560774471e55..6f69b096e387 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java @@ -611,7 +611,7 @@ protected boolean autoscaleCluster(boolean enable, Long minSize, Long maxSize) { if (enable) { String command = String.format("sudo /opt/bin/autoscale-kube-cluster -i %s -e -M %d -m %d", kubernetesCluster.getUuid(), maxSize, minSize); - Pair result = SshHelper.sshExecute(publicIpAddress, sshPort, CLUSTER_NODE_VM_USER, + Pair result = SshHelper.sshExecute(publicIpAddress, sshPort, getControlNodeLoginUser(), pkFile, null, command, 10000, 10000, 60000); // Maybe the file isn't present. Try and copy it @@ -626,7 +626,7 @@ protected boolean autoscaleCluster(boolean enable, Long minSize, Long maxSize) { } // If at first you don't succeed ... - result = SshHelper.sshExecute(publicIpAddress, sshPort, CLUSTER_NODE_VM_USER, + result = SshHelper.sshExecute(publicIpAddress, sshPort, getControlNodeLoginUser(), pkFile, null, command, 10000, 10000, 60000); if (!result.first()) { throw new CloudRuntimeException(result.second()); @@ -634,7 +634,7 @@ protected boolean autoscaleCluster(boolean enable, Long minSize, Long maxSize) { } updateKubernetesClusterEntry(true, minSize, maxSize); } else { - Pair result = SshHelper.sshExecute(publicIpAddress, sshPort, CLUSTER_NODE_VM_USER, + Pair result = SshHelper.sshExecute(publicIpAddress, sshPort, getControlNodeLoginUser(), pkFile, null, String.format("sudo /opt/bin/autoscale-kube-cluster -d"), 10000, 10000, 60000); if (!result.first()) { @@ -649,6 +649,7 @@ protected boolean autoscaleCluster(boolean enable, Long minSize, Long maxSize) { return false; } finally { // Deploying the autoscaler might fail but it can be deployed manually too, so no need to go to an alert state + updateLoginUserDetails(null); stateTransitTo(kubernetesCluster.getId(), KubernetesCluster.Event.OperationSucceeded); } } diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorker.java index a68962d6e503..dbd55b95e07c 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorker.java @@ -26,6 +26,7 @@ import javax.inject.Inject; +import org.apache.cloudstack.api.InternalIdentity; import org.apache.cloudstack.context.CallContext; import org.apache.commons.collections.CollectionUtils; import org.apache.log4j.Level; @@ -192,13 +193,13 @@ private boolean removeKubernetesClusterNode(final String ipAddress, final int po while (retryCounter < retries) { retryCounter++; try { - Pair result = SshHelper.sshExecute(ipAddress, port, CLUSTER_NODE_VM_USER, + Pair result = SshHelper.sshExecute(ipAddress, port, getControlNodeLoginUser(), pkFile, null, String.format("sudo /opt/bin/kubectl drain %s --ignore-daemonsets --delete-local-data", hostName), 10000, 10000, 60000); if (!result.first()) { LOGGER.warn(String.format("Draining node: %s on VM : %s in Kubernetes cluster : %s unsuccessful", hostName, userVm.getDisplayName(), kubernetesCluster.getName())); } else { - result = SshHelper.sshExecute(ipAddress, port, CLUSTER_NODE_VM_USER, + result = SshHelper.sshExecute(ipAddress, port, getControlNodeLoginUser(), pkFile, null, String.format("sudo /opt/bin/kubectl delete node %s", hostName), 10000, 10000, 30000); if (result.first()) { @@ -359,6 +360,7 @@ private void scaleUpKubernetesClusterSize(final long newVmCount) throws CloudRun launchPermissionDao.persist(launchPermission); try { clusterVMs = provisionKubernetesClusterNodeVms((int)(newVmCount + kubernetesCluster.getNodeCount()), (int)kubernetesCluster.getNodeCount(), publicIpAddress); + updateLoginUserDetails(clusterVMs.stream().map(InternalIdentity::getId).collect(Collectors.toList())); } catch (CloudRuntimeException | ManagementServerException | ResourceUnavailableException | InsufficientCapacityException e) { logTransitStateToFailedIfNeededAndThrow(Level.ERROR, String.format("Scaling failed for Kubernetes cluster : %s, unable to provision node VM in the cluster", kubernetesCluster.getName()), e); } @@ -372,7 +374,7 @@ private void scaleUpKubernetesClusterSize(final long newVmCount) throws CloudRun KubernetesClusterVO kubernetesClusterVO = kubernetesClusterDao.findById(kubernetesCluster.getId()); kubernetesClusterVO.setNodeCount(clusterSize); boolean readyNodesCountValid = KubernetesClusterUtil.validateKubernetesClusterReadyNodesCount(kubernetesClusterVO, publicIpAddress, sshPort, - CLUSTER_NODE_VM_USER, sshKeyFile, scaleTimeoutTime, 15000); + getControlNodeLoginUser(), sshKeyFile, scaleTimeoutTime, 15000); detachIsoKubernetesVMs(clusterVMs); deleteTemplateLaunchPermission(); if (!readyNodesCountValid) { // Scaling failed diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java index b64179fb5829..885a52a0367d 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java @@ -57,6 +57,7 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.VmDetailConstants; import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.InternalIdentity; import org.apache.cloudstack.framework.ca.Certificate; import org.apache.cloudstack.utils.security.CertUtils; import org.apache.commons.codec.binary.Base64; @@ -74,6 +75,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; public class KubernetesClusterStartWorker extends KubernetesClusterResourceModifierActionWorker { @@ -462,7 +464,7 @@ private boolean isKubernetesClusterKubeConfigAvailable(final long timeoutTime) { return true; } } - String kubeConfig = KubernetesClusterUtil.getKubernetesClusterConfig(kubernetesCluster, publicIpAddress, sshPort, CLUSTER_NODE_VM_USER, sshKeyFile, timeoutTime); + String kubeConfig = KubernetesClusterUtil.getKubernetesClusterConfig(kubernetesCluster, publicIpAddress, sshPort, getControlNodeLoginUser(), sshKeyFile, timeoutTime); if (StringUtils.isNotEmpty(kubeConfig)) { final String controlVMPrivateIpAddress = getControlVmPrivateIp(); if (StringUtils.isNotEmpty(controlVMPrivateIpAddress)) { @@ -482,7 +484,7 @@ private boolean isKubernetesClusterDashboardServiceRunning(final boolean onCreat return true; } } - if (KubernetesClusterUtil.isKubernetesClusterDashboardServiceRunning(kubernetesCluster, publicIpAddress, sshPort, CLUSTER_NODE_VM_USER, sshKeyFile, timeoutTime, 15000)) { + if (KubernetesClusterUtil.isKubernetesClusterDashboardServiceRunning(kubernetesCluster, publicIpAddress, sshPort, getControlNodeLoginUser(), sshKeyFile, timeoutTime, 15000)) { kubernetesClusterDetailsDao.addDetail(kubernetesCluster.getId(), "dashboardServiceRunning", String.valueOf(true), false); return true; } @@ -578,7 +580,7 @@ public boolean startKubernetesClusterOnCreate() { sshPort = publicIpSshPort.second(); updateKubernetesClusterEntryEndpoint(); boolean readyNodesCountValid = KubernetesClusterUtil.validateKubernetesClusterReadyNodesCount(kubernetesCluster, publicIpAddress, sshPort, - CLUSTER_NODE_VM_USER, sshKeyFile, startTimeoutTime, 15000); + getControlNodeLoginUser(), sshKeyFile, startTimeoutTime, 15000); detachIsoKubernetesVMs(clusterVMs); if (!readyNodesCountValid) { logTransitStateAndThrow(Level.ERROR, String.format("Failed to setup Kubernetes cluster : %s as it does not have desired number of nodes in ready state", kubernetesCluster.getName()), kubernetesCluster.getId(), KubernetesCluster.Event.CreateFailed); @@ -591,6 +593,7 @@ public boolean startKubernetesClusterOnCreate() { } taintControlNodes(); deployProvider(); + updateLoginUserDetails(clusterVMs.stream().map(InternalIdentity::getId).collect(Collectors.toList())); stateTransitTo(kubernetesCluster.getId(), KubernetesCluster.Event.OperationSucceeded); return true; } @@ -645,7 +648,7 @@ public boolean reconcileAlertCluster() { } long actualNodeCount = 0; try { - actualNodeCount = KubernetesClusterUtil.getKubernetesClusterReadyNodesCount(kubernetesCluster, publicIpAddress, sshPort, CLUSTER_NODE_VM_USER, sshKeyFile); + actualNodeCount = KubernetesClusterUtil.getKubernetesClusterReadyNodesCount(kubernetesCluster, publicIpAddress, sshPort, getControlNodeLoginUser(), sshKeyFile); } catch (Exception e) { return false; } diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterUpgradeWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterUpgradeWorker.java index c9ea83ea675d..e970cf693945 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterUpgradeWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterUpgradeWorker.java @@ -63,7 +63,7 @@ protected void retrieveScriptFiles() { private Pair runInstallScriptOnVM(final UserVm vm, final int index) throws Exception { int nodeSshPort = sshPort == 22 ? sshPort : sshPort + index; String nodeAddress = (index > 0 && sshPort == 22) ? vm.getPrivateIpAddress() : publicIpAddress; - SshHelper.scpTo(nodeAddress, nodeSshPort, CLUSTER_NODE_VM_USER, sshKeyFile, null, + SshHelper.scpTo(nodeAddress, nodeSshPort, getControlNodeLoginUser(), sshKeyFile, null, "~/", upgradeScriptFile.getAbsolutePath(), "0755"); String cmdStr = String.format("sudo ./%s %s %s %s %s", upgradeScriptFile.getName(), @@ -71,7 +71,7 @@ private Pair runInstallScriptOnVM(final UserVm vm, final int in index == 0 ? "true" : "false", KubernetesVersionManagerImpl.compareSemanticVersions(upgradeVersion.getSemanticVersion(), "1.15.0") < 0 ? "true" : "false", Hypervisor.HypervisorType.VMware.equals(vm.getHypervisorType())); - return SshHelper.sshExecute(nodeAddress, nodeSshPort, CLUSTER_NODE_VM_USER, sshKeyFile, null, + return SshHelper.sshExecute(nodeAddress, nodeSshPort, getControlNodeLoginUser(), sshKeyFile, null, cmdStr, 10000, 10000, 10 * 60 * 1000); } @@ -90,7 +90,7 @@ private void upgradeKubernetesClusterNodes() { vm.getDisplayName(), kubernetesCluster.getName(), upgradeVersion.getSemanticVersion(), upgradeVersion.getUuid())); } try { - result = SshHelper.sshExecute(publicIpAddress, sshPort, CLUSTER_NODE_VM_USER, sshKeyFile, null, + result = SshHelper.sshExecute(publicIpAddress, sshPort, getControlNodeLoginUser(), sshKeyFile, null, String.format("sudo /opt/bin/kubectl drain %s --ignore-daemonsets --delete-local-data", hostName), 10000, 10000, 60000); } catch (Exception e) { @@ -114,11 +114,11 @@ private void upgradeKubernetesClusterNodes() { if (System.currentTimeMillis() > upgradeTimeoutTime) { logTransitStateDetachIsoAndThrow(Level.ERROR, String.format("Failed to upgrade Kubernetes cluster : %s, upgrade action timed out", kubernetesCluster.getName()), kubernetesCluster, clusterVMs, KubernetesCluster.Event.OperationFailed, null); } - if (!KubernetesClusterUtil.uncordonKubernetesClusterNode(kubernetesCluster, publicIpAddress, sshPort, CLUSTER_NODE_VM_USER, getManagementServerSshPublicKeyFile(), vm, upgradeTimeoutTime, 15000)) { + if (!KubernetesClusterUtil.uncordonKubernetesClusterNode(kubernetesCluster, publicIpAddress, sshPort, getControlNodeLoginUser(), getManagementServerSshPublicKeyFile(), vm, upgradeTimeoutTime, 15000)) { logTransitStateDetachIsoAndThrow(Level.ERROR, String.format("Failed to upgrade Kubernetes cluster : %s, unable to uncordon Kubernetes node on VM : %s", kubernetesCluster.getName(), vm.getDisplayName()), kubernetesCluster, clusterVMs, KubernetesCluster.Event.OperationFailed, null); } if (i == 0) { // Wait for control node to get in Ready state - if (!KubernetesClusterUtil.isKubernetesClusterNodeReady(kubernetesCluster, publicIpAddress, sshPort, CLUSTER_NODE_VM_USER, getManagementServerSshPublicKeyFile(), hostName, upgradeTimeoutTime, 15000)) { + if (!KubernetesClusterUtil.isKubernetesClusterNodeReady(kubernetesCluster, publicIpAddress, sshPort, getControlNodeLoginUser(), getManagementServerSshPublicKeyFile(), hostName, upgradeTimeoutTime, 15000)) { logTransitStateDetachIsoAndThrow(Level.ERROR, String.format("Failed to upgrade Kubernetes cluster : %s, unable to get control Kubernetes node on VM : %s in ready state", kubernetesCluster.getName(), vm.getDisplayName()), kubernetesCluster, clusterVMs, KubernetesCluster.Event.OperationFailed, null); } } From c7fd6def456dd697639329a7a9e2b6f5f212b2cc Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Tue, 7 Dec 2021 13:09:16 +0530 Subject: [PATCH 26/68] Support for live patching systemVMs and deprecating systemVM.iso. Includes: - fix systemVM template version - Include agent.zip, cloud-scripts.tgz to the commons package - Support for live-patching systemVMs - CPVM, SSVM, Routers - Fix Unit test - Remove systemvm.iso dependency --- .../main/java/com/cloud/event/EventTypes.java | 4 + .../com/cloud/server/ManagementService.java | 2 + .../admin/systemvm/PatchSystemVMCmd.java | 107 +++++++++ .../cloud/agent/api/PatchSystemVmAnswer.java | 44 ++++ .../cloud/agent/api/PatchSystemVmCommand.java | 29 +++ debian/rules | 3 +- engine/schema/pom.xml | 9 +- .../cloud/upgrade/DatabaseUpgradeChecker.java | 9 +- .../upgrade/SystemVmTemplateRegistration.java | 22 +- .../META-INF/db/schema-41600to41610.sql | 2 + engine/schema/templateConfig.sh | 20 +- packaging/centos7/cloud.spec | 7 +- packaging/centos8/cloud.spec | 7 +- packaging/suse15/cloud.spec | 7 +- .../resource/LibvirtComputingResource.java | 10 +- .../LibvirtPatchSystemVmCommandWrapper.java | 132 +++++++++++ .../wrapper/LibvirtStartCommandWrapper.java | 21 ++ .../LibvirtComputingResourceTest.java | 11 +- pom.xml | 1 + .../vm/hypervisor/xenserver/xcpserver/patch | 2 + .../cloud/api/ResponseObjectTypeAdapter.java | 4 + .../cloud/server/ManagementServerImpl.java | 90 +++++++- .../systemd/system/cloud-early-config.service | 7 +- .../etc/systemd/system/cloud-postinit.service | 2 +- .../etc/systemd/system/cloud-preinit.service | 18 ++ .../debian/opt/cloud/bin/setup/bootstrap.sh | 134 +---------- .../debian/opt/cloud/bin/setup/cksnode.sh | 2 +- .../opt/cloud/bin/setup/cloud-early-config | 73 +++--- systemvm/debian/opt/cloud/bin/setup/common.sh | 2 +- .../opt/cloud/bin/setup/consoleproxy.sh | 12 - .../debian/opt/cloud/bin/setup/dhcpsrvr.sh | 16 +- systemvm/debian/opt/cloud/bin/setup/elbvm.sh | 9 - systemvm/debian/opt/cloud/bin/setup/ilbvm.sh | 2 +- systemvm/debian/opt/cloud/bin/setup/init.sh | 217 ++++++++++++++++++ .../debian/opt/cloud/bin/setup/postinit.sh | 16 +- systemvm/debian/opt/cloud/bin/setup/router.sh | 19 -- .../debian/opt/cloud/bin/setup/secstorage.sh | 9 - .../debian/opt/cloud/bin/setup/vpcrouter.sh | 3 +- systemvm/patch-sysvms.sh | 108 +++++++++ systemvm/pom.xml | 6 + tools/appliance/build.sh | 8 +- .../scripts/configure_systemvm_services.sh | 1 + .../appliance/systemvmtemplate/template.json | 4 +- .../java/com/cloud/utils/EncryptionUtil.java | 16 ++ .../java/com/cloud/utils/ssh/SshHelper.java | 42 ++++ 45 files changed, 970 insertions(+), 299 deletions(-) create mode 100644 api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java create mode 100644 core/src/main/java/com/cloud/agent/api/PatchSystemVmAnswer.java create mode 100644 core/src/main/java/com/cloud/agent/api/PatchSystemVmCommand.java create mode 100644 plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java create mode 100644 systemvm/debian/etc/systemd/system/cloud-preinit.service create mode 100644 systemvm/debian/opt/cloud/bin/setup/init.sh create mode 100644 systemvm/patch-sysvms.sh diff --git a/api/src/main/java/com/cloud/event/EventTypes.java b/api/src/main/java/com/cloud/event/EventTypes.java index 84514493e941..470c4de16d00 100644 --- a/api/src/main/java/com/cloud/event/EventTypes.java +++ b/api/src/main/java/com/cloud/event/EventTypes.java @@ -636,6 +636,9 @@ public class EventTypes { // Storage Policies public static final String EVENT_IMPORT_VCENTER_STORAGE_POLICIES = "IMPORT.VCENTER.STORAGE.POLICIES"; + // SystemVM + public static final String EVENT_LIVE_PATCH_SYSTEMVM = "LIVE.PATCH.SYSTEM.VM"; + static { // TODO: need a way to force author adding event types to declare the entity details as well, with out braking @@ -1047,6 +1050,7 @@ public class EventTypes { entityEventDetails.put(EVENT_IMPORT_VCENTER_STORAGE_POLICIES, "StoragePolicies"); entityEventDetails.put(EVENT_IMAGE_STORE_DATA_MIGRATE, ImageStore.class); + entityEventDetails.put(EVENT_LIVE_PATCH_SYSTEMVM, "SystemVMs"); } public static String getEntityForEvent(String eventName) { diff --git a/api/src/main/java/com/cloud/server/ManagementService.java b/api/src/main/java/com/cloud/server/ManagementService.java index a11123139619..27e36ea1fa87 100644 --- a/api/src/main/java/com/cloud/server/ManagementService.java +++ b/api/src/main/java/com/cloud/server/ManagementService.java @@ -39,6 +39,7 @@ import org.apache.cloudstack.api.command.admin.resource.UploadCustomCertificateCmd; import org.apache.cloudstack.api.command.admin.systemvm.DestroySystemVmCmd; import org.apache.cloudstack.api.command.admin.systemvm.ListSystemVMsCmd; +import org.apache.cloudstack.api.command.admin.systemvm.PatchSystemVMCmd; import org.apache.cloudstack.api.command.admin.systemvm.RebootSystemVmCmd; import org.apache.cloudstack.api.command.admin.systemvm.ScaleSystemVMCmd; import org.apache.cloudstack.api.command.admin.systemvm.StopSystemVmCmd; @@ -427,5 +428,6 @@ VirtualMachine upgradeSystemVM(ScaleSystemVMCmd cmd) throws ResourceUnavailableE void cleanupVMReservations(); + Pair patchSystemVM(PatchSystemVMCmd cmd); } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java new file mode 100644 index 000000000000..481e62cffb54 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java @@ -0,0 +1,107 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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.apache.cloudstack.api.command.admin.systemvm; + +import com.cloud.event.EventTypes; +import com.cloud.user.Account; +import com.cloud.utils.Pair; +import com.cloud.vm.VirtualMachine; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.api.response.SystemVmResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.log4j.Logger; + +@APICommand(name = "patchSystemVm", description = "Attempts to live patch systemVMs - CPVM, SSVM, Routers ", + responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, + responseHasSensitiveInfo = false, authorized = { RoleType.Admin }) +public class PatchSystemVMCmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(PatchSystemVMCmd.class.getName()); + private static final String s_name = "patchsystemvmresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = SystemVmResponse.class, + description = "patches systemVM - CPVM/SSVM/Router with the specified ID") + private Long id; + + @Parameter(name = ApiConstants.FORCED, type = CommandType.BOOLEAN, + description = "If true, initiates copy of scripts and restart of the agent if if the template version is the latest." + + "To be used with ID parameter only") + private Boolean force; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + + public Long getId() { + return id; + } + + public boolean isForced() { + return force != null ? force : false; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getEventType() { + return EventTypes.EVENT_LIVE_PATCH_SYSTEMVM; + } + + @Override + public String getEventDescription() { + return String.format("Attempting to live patch System VM with Id: %s ", this._uuidMgr.getUuid(VirtualMachine.class, getId())); + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + Account account = CallContext.current().getCallingAccount(); + if (account != null) { + return account.getId(); + } + + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute() { + Pair patched = _mgr.patchSystemVM(this); + if (patched.first()) { + final SuccessResponse response = new SuccessResponse(getCommandName()); + response.setDisplayText(patched.second()); + setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, patched.second()); + } + } +} diff --git a/core/src/main/java/com/cloud/agent/api/PatchSystemVmAnswer.java b/core/src/main/java/com/cloud/agent/api/PatchSystemVmAnswer.java new file mode 100644 index 000000000000..1065768d6ef2 --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/PatchSystemVmAnswer.java @@ -0,0 +1,44 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.agent.api; + +public class PatchSystemVmAnswer extends Answer { + + String templateVersion; + String scriptsVersion; + + public PatchSystemVmAnswer() { + } + + public PatchSystemVmAnswer(PatchSystemVmCommand cmd, String details, String templateVersion, String scriptsVersion) { + super(cmd, true, details); + this.templateVersion = templateVersion; + this.scriptsVersion = scriptsVersion; + } + + public PatchSystemVmAnswer(PatchSystemVmCommand cmd, String details) { + super(cmd, false, details); + } + + public String getTemplateVersion() { + return this.templateVersion; + } + + public String getScriptsVersion() { + return this.scriptsVersion; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/PatchSystemVmCommand.java b/core/src/main/java/com/cloud/agent/api/PatchSystemVmCommand.java new file mode 100644 index 000000000000..b9ea2d62963b --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/PatchSystemVmCommand.java @@ -0,0 +1,29 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.agent.api; + +public class PatchSystemVmCommand extends GetDomRVersionCmd { + boolean forced; + + public boolean isForced() { + return forced; + } + + public void setForced(boolean forced) { + this.forced = forced; + } +} diff --git a/debian/rules b/debian/rules index ed1559a46dfe..1e7f119f47e9 100755 --- a/debian/rules +++ b/debian/rules @@ -128,7 +128,8 @@ override_dh_auto_install: install -D client/target/utilities/bin/cloud-setup-management $(DESTDIR)/usr/bin/cloudstack-setup-management install -D client/target/utilities/bin/cloud-setup-encryption $(DESTDIR)/usr/bin/cloudstack-setup-encryption install -D client/target/utilities/bin/cloud-sysvmadm $(DESTDIR)/usr/bin/cloudstack-sysvmadm - install -D systemvm/dist/systemvm.iso $(DESTDIR)/usr/share/$(PACKAGE)-common/vms/systemvm.iso + #install -D systemvm/dist/systemvm.iso $(DESTDIR)/usr/share/$(PACKAGE)-common/vms/systemvm.iso + install -D systemvm/dist/* $(DESTDIR)/usr/share/$(PACKAGE)-common/vms/ # We need jasypt for cloud-install-sys-tmplt, so this is a nasty hack to get it into the right place install -D agent/target/dependencies/jasypt-1.9.3.jar $(DESTDIR)/usr/share/$(PACKAGE)-common/lib diff --git a/engine/schema/pom.xml b/engine/schema/pom.xml index edd664eb4c15..adee9110007b 100644 --- a/engine/schema/pom.xml +++ b/engine/schema/pom.xml @@ -73,10 +73,11 @@ - def projectVersion = project.version + def projectVersion = project.properties['project.systemvm.template.version'] + println(projectVersion) String[] versionParts = projectVersion.tokenize('.') - pom.properties['cs.version'] = "4.16" - pom.properties['patch.version'] = "0" + pom.properties['cs.version'] = versionParts[0] + "." + versionParts[1] + pom.properties['patch.version'] = versionParts[2] @@ -146,7 +147,7 @@ bash templateConfig.sh - ${project.version} + ${project.systemvm.template.version} diff --git a/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java b/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java index d2513056216a..1a189c0d2968 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/DatabaseUpgradeChecker.java @@ -369,10 +369,11 @@ public void check() { return; } - SystemVmTemplateRegistration.parseMetadataFile(); - final CloudStackVersion currentVersion = CloudStackVersion.parse(currentVersionValue); - SystemVmTemplateRegistration.CS_MAJOR_VERSION = String.valueOf(currentVersion.getMajorRelease()) + "." + String.valueOf(currentVersion.getMinorRelease()); - SystemVmTemplateRegistration.CS_TINY_VERSION = String.valueOf(currentVersion.getPatchRelease()); + String csVersion = SystemVmTemplateRegistration.parseMetadataFile(); + final CloudStackVersion sysVmVersion = CloudStackVersion.parse(csVersion); + final CloudStackVersion currentVersion = CloudStackVersion.parse(currentVersionValue); + SystemVmTemplateRegistration.CS_MAJOR_VERSION = String.valueOf(sysVmVersion.getMajorRelease()) + "." + String.valueOf(sysVmVersion.getMinorRelease()); + SystemVmTemplateRegistration.CS_TINY_VERSION = String.valueOf(sysVmVersion.getPatchRelease()); s_logger.info("DB version = " + dbVersion + " Code Version = " + currentVersion); diff --git a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java index d788adac8244..4119b11ae508 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java @@ -36,6 +36,7 @@ import com.cloud.upgrade.dao.BasicTemplateDataStoreDaoImpl; import com.cloud.user.Account; import com.cloud.utils.DateUtil; +import com.cloud.utils.EncryptionUtil; import com.cloud.utils.Pair; import com.cloud.utils.UriUtils; import com.cloud.utils.db.GlobalLock; @@ -54,7 +55,6 @@ import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; -import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.ini4j.Ini; @@ -64,7 +64,6 @@ import java.io.File; import java.io.FileReader; import java.io.IOException; -import java.io.InputStream; import java.net.URI; import java.nio.file.Files; import java.nio.file.Path; @@ -351,16 +350,6 @@ public static boolean validateIfSeeded(String url, String path) { } } - private String calculateChecksum(File file) { - try (InputStream is = Files.newInputStream(Paths.get(file.getPath()))) { - return DigestUtils.md5Hex(is); - } catch (IOException e) { - String errMsg = "Failed to calculate template checksum"; - LOGGER.error(errMsg, e); - throw new CloudRuntimeException(errMsg, e); - } - } - public Long getRegisteredTemplateId(Pair hypervisorAndTemplateName) { VMTemplateVO vmTemplate = vmTemplateDao.findLatestTemplateByName(hypervisorAndTemplateName.second()); Long templateId = null; @@ -690,7 +679,7 @@ public void registerTemplate(Pair hypervisorA } } - public static void parseMetadataFile() { + public static String parseMetadataFile() { try { Ini ini = new Ini(); ini.load(new FileReader(METADATA_FILE)); @@ -702,6 +691,8 @@ public static void parseMetadataFile() { NewTemplateChecksum.put(hypervisorType, section.get("checksum")); NewTemplateUrl.put(hypervisorType, section.get("downloadurl")); } + Ini.Section section = ini.get("default"); + return section.get("version"); } catch (Exception e) { String errMsg = String.format("Failed to parse systemVM template metadata file: %s", METADATA_FILE); LOGGER.error(errMsg, e); @@ -735,7 +726,7 @@ private void validateTemplates(Set hypervisorsInUse) } File tempFile = new File(TEMPLATES_PATH + matchedTemplate); - String templateChecksum = calculateChecksum(tempFile); + String templateChecksum = EncryptionUtil.calculateChecksum(tempFile); if (!templateChecksum.equals(NewTemplateChecksum.get(getHypervisorType(hypervisor)))) { LOGGER.error(String.format("Checksum mismatch: %s != %s ", templateChecksum, NewTemplateChecksum.get(getHypervisorType(hypervisor)))); templatesFound = false; @@ -812,9 +803,6 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { private void updateRegisteredTemplateDetails(Long templateId, Map.Entry hypervisorAndTemplateName) { VMTemplateVO templateVO = vmTemplateDao.findById(templateId); templateVO.setTemplateType(Storage.TemplateType.SYSTEM); - if (Hypervisor.HypervisorType.VMware == templateVO.getHypervisorType()) { - templateVO.setDeployAsIs(true); - } boolean updated = vmTemplateDao.update(templateVO.getId(), templateVO); if (!updated) { String errMsg = String.format("updateSystemVmTemplates:Exception while updating template with id %s to be marked as 'system'", templateId); diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41600to41610.sql b/engine/schema/src/main/resources/META-INF/db/schema-41600to41610.sql index bf9cbf861d73..3967c69954f3 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-41600to41610.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-41600to41610.sql @@ -127,3 +127,5 @@ CALL `cloud_usage`.`IDEMPOTENT_ADD_UNIQUE_INDEX`('cloud_usage.usage_volume', 'id -- Add PK to cloud_usage.usage_vpn_user CALL `cloud_usage`.`IDEMPOTENT_ADD_COLUMN`('cloud_usage.usage_vpn_user', 'id', 'BIGINT(20) NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (`id`)'); + +UPDATE `cloud`.`vm_template` set deploy_as_is = 0 where id = 8; diff --git a/engine/schema/templateConfig.sh b/engine/schema/templateConfig.sh index c3093530e7b2..891c73db1bbf 100644 --- a/engine/schema/templateConfig.sh +++ b/engine/schema/templateConfig.sh @@ -23,8 +23,10 @@ function getTemplateVersion() { subversion1="$(cut -d'.' -f1 <<<"$version")" subversion2="$(cut -d'.' -f2 <<<"$version")" minorversion="$(cut -d'.' -f3 <<<"$version")" + securityversion="$(cut -d'.' -f4 <<<"$version")" export CS_VERSION="${subversion1}"."${subversion2}" export CS_MINOR_VERSION="${minorversion}" + export VERSION="${CS_VERSION}.${CS_MINOR_VERSION}" } function getGenericName() { @@ -52,12 +54,14 @@ function getChecksum() { function createMetadataFile() { local fileData=$(cat $SOURCEFILE) + echo -e "["default"]\nversion = $VERSION.${securityversion}\n" >> $METADATAFILE for i in "${!templates[@]}" do section="$i" hvName=$(getGenericName $i) - templatename="systemvm-${i}-${CS_VERSION}.${CS_MINOR_VERSION}" - checksum=$(getChecksum "$fileData" $hvName) + + templatename="systemvm-${i}-${VERSION}" + checksum=$(getChecksum "$fileData" "$VERSION-$hvName") downloadurl="${templates[$i]}" filename=$(echo ${downloadurl##*'/'}) echo -e "["$section"]\ntemplatename = $templatename\nchecksum = $checksum\ndownloadurl = $downloadurl\nfilename = $filename\n" >> $METADATAFILE @@ -66,12 +70,12 @@ function createMetadataFile() { declare -A templates getTemplateVersion $1 -templates=( ["kvm"]="https://download.cloudstack.org/systemvm/${CS_VERSION}/systemvmtemplate-${CS_VERSION}.${CS_MINOR_VERSION}-kvm.qcow2.bz2" - ["vmware"]="https://download.cloudstack.org/systemvm/${CS_VERSION}/systemvmtemplate-${CS_VERSION}.${CS_MINOR_VERSION}-vmware.ova" - ["xenserver"]="https://download.cloudstack.org/systemvm/$CS_VERSION/systemvmtemplate-$CS_VERSION.$CS_MINOR_VERSION-xen.vhd.bz2" - ["hyperv"]="https://download.cloudstack.org/systemvm/$CS_VERSION/systemvmtemplate-$CS_VERSION.$CS_MINOR_VERSION-hyperv.vhd.zip" - ["lxc"]="https://download.cloudstack.org/systemvm/$CS_VERSION/systemvmtemplate-$CS_VERSION.$CS_MINOR_VERSION-kvm.qcow2.bz2" - ["ovm3"]="https://download.cloudstack.org/systemvm/$CS_VERSION/systemvmtemplate-$CS_VERSION.$CS_MINOR_VERSION-ovm.raw.bz2" ) +templates=( ["kvm"]="https://download.cloudstack.org/systemvm/${CS_VERSION}/systemvmtemplate-$VERSION-kvm.qcow2.bz2" + ["vmware"]="https://download.cloudstack.org/systemvm/${CS_VERSION}/systemvmtemplate-$VERSION-vmware.ova" + ["xenserver"]="https://download.cloudstack.org/systemvm/$CS_VERSION/systemvmtemplate-$VERSION-xen.vhd.bz2" + ["hyperv"]="https://download.cloudstack.org/systemvm/$CS_VERSION/systemvmtemplate-$VERSION-hyperv.vhd.zip" + ["lxc"]="https://download.cloudstack.org/systemvm/$CS_VERSION/systemvmtemplate-$VERSION-kvm.qcow2.bz2" + ["ovm3"]="https://download.cloudstack.org/systemvm/$CS_VERSION/systemvmtemplate-$VERSION-ovm.raw.bz2" ) PARENTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )/dist/systemvm-templates/" diff --git a/packaging/centos7/cloud.spec b/packaging/centos7/cloud.spec index 0e2a5944a0d0..b248cfc3323e 100644 --- a/packaging/centos7/cloud.spec +++ b/packaging/centos7/cloud.spec @@ -231,7 +231,8 @@ mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms mkdir -p ${RPM_BUILD_ROOT}%{python_sitearch}/ mkdir -p ${RPM_BUILD_ROOT}/usr/bin cp -r scripts/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts -install -D systemvm/dist/systemvm.iso ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/systemvm.iso +#install -D systemvm/dist/systemvm.iso ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/systemvm.iso +install -D systemvm/dist/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/ install python/lib/cloud_utils.py ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py cp -r python/lib/cloudutils ${RPM_BUILD_ROOT}%{python_sitearch}/ python3 -m py_compile ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py @@ -600,7 +601,11 @@ pip3 install --upgrade urllib3 %dir %attr(0755,root,root) %{_datadir}/%{name}-common/vms %attr(0755,root,root) %{_datadir}/%{name}-common/scripts %attr(0755,root,root) /usr/bin/cloudstack-sccs +# TODO: Remove systemvm.iso %attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/agent.zip +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/cloud-scripts.tgz +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/patch-sysvms.sh %attr(0644,root,root) %{python_sitearch}/cloud_utils.py %attr(0644,root,root) %{python_sitearch}/__pycache__/* %attr(0644,root,root) %{python_sitearch}/cloudutils/* diff --git a/packaging/centos8/cloud.spec b/packaging/centos8/cloud.spec index 8088ff480c3d..37a374d57e08 100644 --- a/packaging/centos8/cloud.spec +++ b/packaging/centos8/cloud.spec @@ -224,7 +224,8 @@ mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms mkdir -p ${RPM_BUILD_ROOT}%{python_sitearch}/ mkdir -p ${RPM_BUILD_ROOT}/usr/bin cp -r scripts/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts -install -D systemvm/dist/systemvm.iso ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/systemvm.iso +#install -D systemvm/dist/systemvm.iso ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/systemvm.iso +install -D systemvm/dist/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/ install python/lib/cloud_utils.py ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py cp -r python/lib/cloudutils ${RPM_BUILD_ROOT}%{python_sitearch}/ python3 -m py_compile ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py @@ -588,7 +589,11 @@ pip install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz %dir %attr(0755,root,root) %{_datadir}/%{name}-common/vms %attr(0755,root,root) %{_datadir}/%{name}-common/scripts %attr(0755,root,root) /usr/bin/cloudstack-sccs +# TODO: Remove systemvm.iso %attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/agent.zip +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/cloud-scripts.tgz +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/patch-sysvms.sh %attr(0644,root,root) %{python_sitearch}/cloud_utils.py %attr(0644,root,root) %{python_sitearch}/__pycache__/* %attr(0644,root,root) %{python_sitearch}/cloudutils/* diff --git a/packaging/suse15/cloud.spec b/packaging/suse15/cloud.spec index 7e5c38fb9748..23bce9fc92e1 100644 --- a/packaging/suse15/cloud.spec +++ b/packaging/suse15/cloud.spec @@ -226,7 +226,8 @@ mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms mkdir -p ${RPM_BUILD_ROOT}%{python_sitearch}/ mkdir -p ${RPM_BUILD_ROOT}/usr/bin cp -r scripts/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts -install -D systemvm/dist/systemvm.iso ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/systemvm.iso +#install -D systemvm/dist/systemvm.iso ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/systemvm.iso +install -D systemvm/dist/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/ install python/lib/cloud_utils.py ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py cp -r python/lib/cloudutils ${RPM_BUILD_ROOT}%{python_sitearch}/ python3 -m py_compile ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py @@ -582,7 +583,11 @@ pip install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz %dir %attr(0755,root,root) %{_datadir}/%{name}-common/vms %attr(0755,root,root) %{_datadir}/%{name}-common/scripts %attr(0755,root,root) /usr/bin/cloudstack-sccs +# TODO: Remove systemvm.iso %attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/agent.zip +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/cloud-scripts.tgz +%attr(0644, root, root) %{_datadir}/%{name}-common/vms/patch-sysvms.sh %attr(0644,root,root) %{python_sitearch}/cloud_utils.py %attr(0644,root,root) %{python_sitearch}/__pycache__/* %attr(0644,root,root) %{python_sitearch}/cloudutils/* diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index f1c0ce8153c9..a3257f9967bd 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -279,6 +279,10 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv private static final String AARCH64 = "aarch64"; public static final String RESIZE_NOTIFY_ONLY = "NOTIFYONLY"; + public static final String BASEPATH = "/usr/share/cloudstack-common/vms/"; + + public static String[] srcFiles = new String[] { "agent.zip", "cloud-scripts.tgz" }; + public static String[] newSrcFiles = new String[] { "agent.zip", "cloud-scripts.tgz", "patch-sysvms.sh" }; private String _modifyVlanPath; private String _versionstringpath; @@ -402,7 +406,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv s_powerStatesTable.put(DomainState.VIR_DOMAIN_SHUTDOWN, PowerState.PowerOff); } - private VirtualRoutingResource _virtRouterResource; + public VirtualRoutingResource _virtRouterResource; private String _pingTestPath; @@ -462,7 +466,7 @@ public ExecutionResult createFileInVR(final String routerIp, final String path, try { SshHelper.scpTo(routerIp, 3922, "root", permKey, null, path, content.getBytes(), filename, null); } catch (final Exception e) { - s_logger.warn("Fail to create file " + path + filename + " in VR " + routerIp, e); + s_logger.warn("Failed to create file " + path + filename + " in VR " + routerIp, e); details = e.getMessage(); success = false; } @@ -2905,7 +2909,7 @@ public int compare(final DiskTO arg0, final DiskTO arg1) { if (vmSpec.getType() != VirtualMachine.Type.User) { if (_sysvmISOPath != null) { final DiskDef iso = new DiskDef(); - iso.defISODisk(_sysvmISOPath); + // iso.defISODisk(_sysvmISOPath); if (_guestCpuArch != null && _guestCpuArch.equals("aarch64")) { iso.setBusType(DiskDef.DiskBus.SCSI); } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java new file mode 100644 index 000000000000..392ccb6e6584 --- /dev/null +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java @@ -0,0 +1,132 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.hypervisor.kvm.resource.wrapper; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.PatchSystemVmAnswer; +import com.cloud.agent.api.PatchSystemVmCommand; +import com.cloud.agent.api.routing.NetworkElementCommand; +import com.cloud.agent.resource.virtualnetwork.VRScripts; +import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource; +import com.cloud.resource.CommandWrapper; +import com.cloud.resource.ResourceWrapper; +import com.cloud.utils.EncryptionUtil; +import com.cloud.utils.ExecutionResult; +import com.cloud.utils.Pair; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; +import com.cloud.utils.ssh.SshHelper; +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Logger; + +import java.io.File; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +@ResourceWrapper(handles = PatchSystemVmCommand.class) +public class LibvirtPatchSystemVmCommandWrapper extends CommandWrapper { + private static final Logger s_logger = Logger.getLogger(LibvirtPatchSystemVmCommandWrapper.class); + private static int sshPort = Integer.parseInt(LibvirtComputingResource.DEFAULTDOMRSSHPORT); + private static File pemFile = new File(LibvirtComputingResource.SSHPRVKEYPATH); + + @Override + public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverResource) { + final String controlIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); + final String sysVMName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + ExecutionResult result; + try { + result = getSystemVmVersionAndChecksum(serverResource, controlIp); + scpPatchFiles(controlIp); + } catch (CloudRuntimeException e) { + return new PatchSystemVmAnswer(cmd, e.getMessage()); + } + + final String[] lines = result.getDetails().split("&"); + // TODO: do we fail, or patch anyway?? + if (lines.length != 2) { + return new PatchSystemVmAnswer(cmd, result.getDetails()); + } + + String scriptChecksum = lines[1].trim(); + String checksum = calculateCurrentChecksum(sysVMName).trim(); + + if (!StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum)) { + if (!cmd.isForced()) { + String msg = String.format("No change in the scripts checksum, not patching systemVM %s", sysVMName); + s_logger.info(msg); + return new PatchSystemVmAnswer(cmd, msg, lines[0], lines[1]); + } + } + + Pair patchResult = null; + try { + patchResult = SshHelper.sshExecute(controlIp, sshPort, "root", + pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 60000); + } catch (Exception e) { + return new PatchSystemVmAnswer(cmd, e.getMessage()); + } + + if (patchResult.first()) { + return new PatchSystemVmAnswer(cmd, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], lines[1]); + } + return new PatchSystemVmAnswer(cmd, patchResult.second()); + } + + private String calculateCurrentChecksum(String name) { + String cloudScriptsPath = Script.findScript("", "vms/cloud-scripts.tgz"); + if (cloudScriptsPath == null) { + throw new CloudRuntimeException(String.format("Unable to find cloudScripts path, cannot update SystemVM %s", name)); + } + String md5sum = EncryptionUtil.calculateChecksum(new File(cloudScriptsPath)); + return md5sum; + } + + private ExecutionResult getSystemVmVersionAndChecksum(LibvirtComputingResource serverResource, String controlIp) { + ExecutionResult result; + try { + result = serverResource.executeInVR(controlIp, VRScripts.VERSION, null); + if (!result.isSuccess()) { + String errMsg = String.format("GetSystemVMVersionCmd on %s failed, message %s", controlIp, result.getDetails()); + s_logger.error(errMsg); + throw new CloudRuntimeException(errMsg); + } + } catch (final Exception e) { + final String msg = "GetSystemVMVersionCmd failed due to " + e; + s_logger.error(msg, e); + throw new CloudRuntimeException(msg, e); + } + return result; + } + + private void scpPatchFiles(String controlIp) { + try { + List srcFiles = Arrays.asList(LibvirtComputingResource.newSrcFiles); + srcFiles = srcFiles.stream() + .map(file -> LibvirtComputingResource.BASEPATH + file) // Using Lambda notation to update the entries + .collect(Collectors.toList()); + String[] newSrcFiles = srcFiles.toArray(new String[0]); + SshHelper.scpTo(controlIp, sshPort, "root", pemFile, null, + "/home/cloud/", newSrcFiles, "0755"); + } catch (Exception e) { + String errMsg = "Failed to scp files to system VM"; + s_logger.error(errMsg, e); + throw new CloudRuntimeException(errMsg, e); + } + } +} + diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java index f151255d5cdc..b95c163e7081 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java @@ -19,8 +19,13 @@ package com.cloud.hypervisor.kvm.resource.wrapper; +import java.io.File; import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import com.cloud.utils.ssh.SshHelper; import org.apache.log4j.Logger; import org.libvirt.Connect; import org.libvirt.DomainInfo.DomainState; @@ -115,6 +120,22 @@ public Answer execute(final StartCommand command, final LibvirtComputingResource break; } } + + try { + List srcFiles = Arrays.asList(LibvirtComputingResource.srcFiles); + srcFiles = srcFiles.stream() + .map(file -> LibvirtComputingResource.BASEPATH + file) + .collect(Collectors.toList()); + File pemFile = new File(LibvirtComputingResource.SSHPRVKEYPATH); + SshHelper.scpTo(controlIp, 3922, "root", pemFile, null, + "/home/cloud/", srcFiles.toArray(new String[0]), "0755"); + // TODO: May want to remove this when cert patching logic is moved + Thread.sleep(10000); + } catch (Exception e) { + String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; + s_logger.error(errMsg, e); + return new StartAnswer(command, String.format("%s due to: %s", errMsg, e.getMessage())); + } } } diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java index 1f6545881795..f13ac238cfea 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java @@ -54,6 +54,7 @@ import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; +import com.cloud.utils.ssh.SshHelper; import org.apache.cloudstack.storage.command.AttachAnswer; import org.apache.cloudstack.storage.command.AttachCommand; import org.apache.cloudstack.utils.linux.CPUStat; @@ -210,7 +211,7 @@ import org.libvirt.VcpuInfo; @RunWith(PowerMockRunner.class) -@PrepareForTest(value = {MemStat.class}) +@PrepareForTest(value = {MemStat.class, SshHelper.class}) @PowerMockIgnore({"javax.xml.*", "org.w3c.dom.*", "org.apache.xerces.*"}) public class LibvirtComputingResourceTest { @@ -5278,7 +5279,9 @@ public void testStartCommandUriException() { } @Test - public void testStartCommand() { + public void testStartCommand() throws Exception { + PowerMockito.mockStatic(SshHelper.class); + PowerMockito.doNothing().when(SshHelper.class, "scpTo", Mockito.anyString(), Mockito.anyInt(), Mockito.anyString(), Mockito.any(File.class), nullable(String.class), Mockito.anyString(), Mockito.any(String[].class), Mockito.anyString()); final VirtualMachineTO vmSpec = Mockito.mock(VirtualMachineTO.class); final com.cloud.host.Host host = Mockito.mock(com.cloud.host.Host.class); final boolean executeInSequence = false; @@ -5352,7 +5355,9 @@ public void testStartCommand() { } @Test - public void testStartCommandIsolationEc2() { + public void testStartCommandIsolationEc2() throws Exception { + PowerMockito.mockStatic(SshHelper.class); + PowerMockito.doNothing().when(SshHelper.class, "scpTo", Mockito.anyString(), Mockito.anyInt(), Mockito.anyString(), Mockito.any(File.class), nullable(String.class), Mockito.anyString(), Mockito.any(String[].class), Mockito.anyString()); final VirtualMachineTO vmSpec = Mockito.mock(VirtualMachineTO.class); final com.cloud.host.Host host = Mockito.mock(com.cloud.host.Host.class); final boolean executeInSequence = false; diff --git a/pom.xml b/pom.xml index cfea12556552..718430eb867e 100644 --- a/pom.xml +++ b/pom.xml @@ -49,6 +49,7 @@ UTF-8 UTF-8 + 4.16.0.0 11 diff --git a/scripts/vm/hypervisor/xenserver/xcpserver/patch b/scripts/vm/hypervisor/xenserver/xcpserver/patch index 862aa2e9c110..32c7c46728d8 100644 --- a/scripts/vm/hypervisor/xenserver/xcpserver/patch +++ b/scripts/vm/hypervisor/xenserver/xcpserver/patch @@ -32,6 +32,8 @@ vmops=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +agent.zip=../../../../../vms,0644,/opt/xensource/packages/iso +cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/iso id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin setupxenserver.sh=..,0755,/opt/cloud/bin diff --git a/server/src/main/java/com/cloud/api/ResponseObjectTypeAdapter.java b/server/src/main/java/com/cloud/api/ResponseObjectTypeAdapter.java index 44baedc933b1..f6f777efe3f9 100644 --- a/server/src/main/java/com/cloud/api/ResponseObjectTypeAdapter.java +++ b/server/src/main/java/com/cloud/api/ResponseObjectTypeAdapter.java @@ -22,6 +22,7 @@ import org.apache.cloudstack.api.ResponseObject; import org.apache.cloudstack.api.response.ExceptionResponse; import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import com.google.gson.JsonElement; @@ -38,6 +39,9 @@ public JsonElement serialize(ResponseObject responseObj, Type typeOfResponseObj, if (responseObj instanceof SuccessResponse) { obj.addProperty("success", ((SuccessResponse)responseObj).getSuccess()); + if (!StringUtils.isEmpty(((SuccessResponse) responseObj).getDisplayText())) { + obj.addProperty("details", ((SuccessResponse)responseObj).getDisplayText()); + } return obj; } else if (responseObj instanceof ExceptionResponse) { obj.addProperty("errorcode", ((ExceptionResponse)responseObj).getErrorCode()); diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index cc53eed7d644..2a0734d7ec3a 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -44,8 +44,15 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.agent.api.PatchSystemVmAnswer; +import com.cloud.agent.api.PatchSystemVmCommand; +import com.cloud.agent.api.routing.NetworkElementCommand; import com.cloud.dc.DomainVlanMapVO; import com.cloud.dc.dao.DomainVlanMapDao; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.network.Networks; +import com.cloud.vm.NicVO; +import com.cloud.vm.dao.NicDao; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.affinity.AffinityGroupProcessor; import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; @@ -225,6 +232,7 @@ import org.apache.cloudstack.api.command.admin.systemvm.DestroySystemVmCmd; import org.apache.cloudstack.api.command.admin.systemvm.ListSystemVMsCmd; import org.apache.cloudstack.api.command.admin.systemvm.MigrateSystemVMCmd; +import org.apache.cloudstack.api.command.admin.systemvm.PatchSystemVMCmd; import org.apache.cloudstack.api.command.admin.systemvm.RebootSystemVmCmd; import org.apache.cloudstack.api.command.admin.systemvm.ScaleSystemVMCmd; import org.apache.cloudstack.api.command.admin.systemvm.StartSystemVMCmd; @@ -763,6 +771,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe static final ConfigKey sshKeyLength = new ConfigKey("Advanced", Integer.class, "ssh.key.length", "2048", "Specifies custom SSH key length (bit)", true, ConfigKey.Scope.Global); static final ConfigKey humanReadableSizes = new ConfigKey("Advanced", Boolean.class, "display.human.readable.sizes", "true", "Enables outputting human readable byte sizes to logs and usage records.", false, ConfigKey.Scope.Global); public static final ConfigKey customCsIdentifier = new ConfigKey("Advanced", String.class, "custom.cs.identifier", UUID.randomUUID().toString().split("-")[0].substring(4), "Custom identifier for the cloudstack installation", true, ConfigKey.Scope.Global); + private static final VirtualMachine.Type []systemVmTypes = { VirtualMachine.Type.SecondaryStorageVm, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.DomainRouter }; @Inject public AccountManager _accountMgr; @@ -825,7 +834,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe @Inject private StoragePoolJoinDao _poolJoinDao; @Inject - private NetworkDao _networkDao; + private NetworkDao networkDao; @Inject private StorageManager _storageMgr; @Inject @@ -898,6 +907,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe private AnnotationDao annotationDao; @Inject private DomainVlanMapDao _domainVlanMapDao; + @Inject + private NicDao nicDao; private LockControllerListener _lockControllerListener; private final ScheduledExecutorService _eventExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("EventChecker")); @@ -2172,9 +2183,9 @@ public Pair, Integer> searchForIPAddresses(final ListP if (ip == null) { throw new InvalidParameterValueException("Please specify a valid ipaddress id"); } - network = _networkDao.findById(ip.getSourceNetworkId()); + network = networkDao.findById(ip.getSourceNetworkId()); } else { - network = _networkDao.findById(networkId); + network = networkDao.findById(networkId); } if (network == null || network.getGuestType() != Network.GuestType.Shared) { throw new InvalidParameterValueException("Please specify a valid network id"); @@ -2236,7 +2247,7 @@ public Pair, Integer> searchForIPAddresses(final ListP } if (associatedNetworkId != null) { - _accountMgr.checkAccess(caller, null, false, _networkDao.findById(associatedNetworkId)); + _accountMgr.checkAccess(caller, null, false, networkDao.findById(associatedNetworkId)); sc.setParameters("associatedNetworkIdEq", associatedNetworkId); } if (vpcId != null) { @@ -2252,7 +2263,7 @@ public Pair, Integer> searchForIPAddresses(final ListP Long zoneId = zone; Account owner = _accountMgr.finalizeOwner(CallContext.current().getCallingAccount(), cmd.getAccountName(), cmd.getDomainId(), cmd.getProjectId()); if (associatedNetworkId != null) { - NetworkVO guestNetwork = _networkDao.findById(associatedNetworkId); + NetworkVO guestNetwork = networkDao.findById(associatedNetworkId); if (zoneId == null) { zoneId = guestNetwork.getDataCenterId(); } else if (zoneId != guestNetwork.getDataCenterId()) { @@ -3527,6 +3538,7 @@ public List> getCommands() { cmdList.add(UploadResourceIconCmd.class); cmdList.add(DeleteResourceIconCmd.class); cmdList.add(ListResourceIconCmd.class); + cmdList.add(PatchSystemVMCmd.class); // Out-of-band management APIs for admins cmdList.add(EnableOutOfBandManagementForHostCmd.class); @@ -3932,7 +3944,7 @@ public Map listCapabilities(final ListCapabilitiesCmd cmd) { boolean elasticLoadBalancerEnabled = false; boolean KVMSnapshotEnabled = false; String supportELB = "false"; - final List networks = _networkDao.listSecurityGroupEnabledNetworks(); + final List networks = networkDao.listSecurityGroupEnabledNetworks(); if (networks != null && !networks.isEmpty()) { securityGroupsEnabled = true; final String elbEnabled = _configDao.getValue(Config.ElasticLoadBalancerEnabled.key()); @@ -4633,6 +4645,72 @@ public void cleanupVMReservations() { _dpMgr.cleanupVMReservations(); } + @Override + public Pair patchSystemVM(PatchSystemVMCmd cmd) { + Long systemVmId = cmd.getId(); + boolean forced = cmd.isForced(); + + if (systemVmId == null) { + throw new InvalidParameterValueException("Please provide a valid ID of a system VM to be patched"); + } + + final VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(systemVmId, systemVmTypes); + if (systemVm == null) { + throw new InvalidParameterValueException("Unable to find SystemVm with id " + systemVmId); + } + + return updateSystemVM(systemVm, forced); + } + + + private String getControlIp(final long systemVmId) { + String controlIpAddress = null; + final List nics = nicDao.listByVmId(systemVmId); + for (final NicVO n : nics) { + final NetworkVO nc = networkDao.findById(n.getNetworkId()); + if (nc != null && nc.getTrafficType() == Networks.TrafficType.Control) { + controlIpAddress = n.getIPv4Address(); + // router will have only one control IP + break; + } + } + + if (controlIpAddress == null) { + s_logger.warn("Unable to find systemVm's control ip in its attached NICs!. systemVmId: " + systemVmId); + VMInstanceVO systemVM = _vmInstanceDao.findById(systemVmId); + return systemVM.getPrivateIpAddress(); + } + + return controlIpAddress; + } + + private Pair updateSystemVM(VMInstanceVO systemVM, boolean forced) { + return patchSystemVm(systemVM, forced); + } + + private Pair patchSystemVm(VMInstanceVO systemVM, boolean forced) { + PatchSystemVmAnswer answer = new PatchSystemVmAnswer(); + final PatchSystemVmCommand command = new PatchSystemVmCommand(); + command.setAccessDetail(NetworkElementCommand.ROUTER_IP, getControlIp(systemVM.getId())); + command.setAccessDetail(NetworkElementCommand.ROUTER_NAME, systemVM.getInstanceName()); + command.setForced(forced); + try { + answer = (PatchSystemVmAnswer) _agentMgr.send(systemVM.getHostId(), command); + if (!answer.getResult()) { + String errMsg = String.format("Failed to patch systemVM %s due to %s", systemVM.getInstanceName(), answer.getDetails()); + s_logger.error(errMsg); + return new Pair<>(false, errMsg); + } + + } catch (AgentUnavailableException | OperationTimedoutException e) { + String errMsg = "SystemVM live patch failed"; + s_logger.error(errMsg, e); + return new Pair<>(false, String.format("%s due to: %s", errMsg, e.getMessage())); + } + s_logger.info(String.format("Successfully patch system VM %s", systemVM.getInstanceName())); + return new Pair<>(true, answer.getDetails()); + } + public List getStoragePoolAllocators() { return _storagePoolAllocators; } diff --git a/systemvm/debian/etc/systemd/system/cloud-early-config.service b/systemvm/debian/etc/systemd/system/cloud-early-config.service index 2af52767cc39..cfaf5e7cd44a 100644 --- a/systemvm/debian/etc/systemd/system/cloud-early-config.service +++ b/systemvm/debian/etc/systemd/system/cloud-early-config.service @@ -2,11 +2,8 @@ Description=CloudStack post-boot patching service using cmdline DefaultDependencies=no -Before=network-pre.target -Wants=network-pre.target - -Requires=local-fs.target -After=local-fs.target +Requires=local-fs.target cloud-preinit.service +After=local-fs.target cloud-preinit.service [Install] WantedBy=multi-user.target diff --git a/systemvm/debian/etc/systemd/system/cloud-postinit.service b/systemvm/debian/etc/systemd/system/cloud-postinit.service index cb20aaf7c060..f5b23e230877 100644 --- a/systemvm/debian/etc/systemd/system/cloud-postinit.service +++ b/systemvm/debian/etc/systemd/system/cloud-postinit.service @@ -1,7 +1,7 @@ [Unit] Description=CloudStack post-patching init script After=cloud-early-config.service network.target local-fs.target -Before=ssh.service +#Before=ssh.service [Install] WantedBy=multi-user.target diff --git a/systemvm/debian/etc/systemd/system/cloud-preinit.service b/systemvm/debian/etc/systemd/system/cloud-preinit.service new file mode 100644 index 000000000000..373cd9ed66fa --- /dev/null +++ b/systemvm/debian/etc/systemd/system/cloud-preinit.service @@ -0,0 +1,18 @@ +[Unit] +Description=CloudStack service to initialize interfaces +DefaultDependencies=no + +Before=network-pre.target +Wants=network-pre.target + +Requires=local-fs.target +After=local-fs.target + +[Install] +WantedBy=multi-user.target + +[Service] +Type=oneshot +ExecStart=/opt/cloud/bin/setup/init.sh +RemainAfterExit=true +TimeoutStartSec=5min diff --git a/systemvm/debian/opt/cloud/bin/setup/bootstrap.sh b/systemvm/debian/opt/cloud/bin/setup/bootstrap.sh index 2335d649a950..3f64be778232 100755 --- a/systemvm/debian/opt/cloud/bin/setup/bootstrap.sh +++ b/systemvm/debian/opt/cloud/bin/setup/bootstrap.sh @@ -15,7 +15,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. - +set -x PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" CMDLINE=/var/cache/cloud/cmdline @@ -29,124 +29,6 @@ log_it() { log_action_msg "$@" } -hypervisor() { - if [ -d /proc/xen ]; then - mount -t xenfs none /proc/xen - $(dmesg | grep -q "Xen HVM") - if [ $? -eq 0 ]; then # 1=PV,0=HVM - echo "xen-hvm" && return 0 - else - echo "xen-pv" && return 0 - fi - fi - - [ -x /usr/sbin/virt-what ] && local facts=( $(virt-what) ) - if [ "$facts" != "" ]; then - # Xen HVM is recognized as Hyperv when Viridian extensions are enabled - if [ "${facts[-1]}" == "xen-domU" ] && [ "${facts[0]}" == "hyperv" ]; then - echo "xen-hvm" && return 0 - else - echo ${facts[-1]} && return 0 - fi - fi - - grep -q QEMU /proc/cpuinfo && echo "kvm" && return 0 - grep -q QEMU /var/log/messages && echo "kvm" && return 0 - - vmware-checkvm &> /dev/null && echo "vmware" && return 0 - - echo "unknown" && return 1 -} - -config_guest() { - [ ! -d /proc/xen ] && sed -i 's/^vc/#vc/' /etc/inittab && telinit q - [ -d /proc/xen ] && sed -i 's/^#vc/vc/' /etc/inittab && telinit q - - systemctl daemon-reload - - case $HYPERVISOR in - xen-pv|xen-domU) - systemctl stop ntpd - systemctl disable ntpd - systemctl enable xe-daemon - systemctl start xe-daemon - - cat /proc/cmdline > $CMDLINE - sed -i "s/%/ /g" $CMDLINE - ;; - xen-hvm) - systemctl stop ntpd - systemctl disable ntpd - systemctl enable xe-daemon - systemctl start xe-daemon - - if [ ! -f /usr/bin/xenstore-read ]; then - log_it "ERROR: xentools not installed, cannot found xenstore-read" && exit 5 - fi - /usr/bin/xenstore-read vm-data/cloudstack/init > $CMDLINE - sed -i "s/%/ /g" $CMDLINE - ;; - kvm) - # Configure kvm hotplug support - if grep -E 'CONFIG_HOTPLUG_PCI=y|CONFIG_HOTPLUG_PCI_ACPI=y' /boot/config-`uname -r`; then - log_it "acpiphp and pci_hotplug module already compiled in" - else - modprobe acpiphp 2> /dev/null && log_it "acpiphp module loaded" || true - modprobe pci_hotplug 2> /dev/null && log_it "pci_hotplug module loaded" || true - fi - - sed -i -e "/^s0:2345:respawn.*/d" /etc/inittab - sed -i -e "/6:23:respawn/a\s0:2345:respawn:/sbin/getty -L 115200 ttyS0 vt102" /etc/inittab - systemctl enable qemu-guest-agent - systemctl start qemu-guest-agent - - # Wait for $CMDLINE file to be written by the qemu-guest-agent - for i in {1..60}; do - if [ -s $CMDLINE ]; then - log_it "Received a new non-empty cmdline file from qemu-guest-agent" - # Remove old configuration files in /etc/cloudstack if VR is booted from cloudstack - rm -rf /etc/cloudstack/*.json - log_it "Booting from cloudstack, remove old configuration files in /etc/cloudstack/" - break - fi - sleep 1 - done - if [ ! -s $CMDLINE ]; then - log_it "Failed to receive the cmdline file via the qemu-guest-agent" - fi - ;; - vmware) - # system time sync'd with host via vmware tools - systemctl stop ntpd - systemctl disable ntpd - systemctl enable open-vm-tools - systemctl start open-vm-tools - - vmtoolsd --cmd 'machine.id.get' > $CMDLINE - ;; - virtualpc|hyperv) - # Hyper-V is recognized as virtualpc hypervisor type. Boot args are passed using KVP Daemon - systemctl enable hyperv-daemons.hv-fcopy-daemon.service hyperv-daemons.hv-kvp-daemon.service hyperv-daemons.hv-vss-daemon.service - systemctl start hyperv-daemons.hv-fcopy-daemon.service hyperv-daemons.hv-kvp-daemon.service hyperv-daemons.hv-vss-daemon.service - sleep 5 - cp -f /var/opt/hyperv/.kvp_pool_0 $CMDLINE - cat /dev/null > /var/opt/hyperv/.kvp_pool_0 - ;; - virtualbox) - # Virtualbox is used to test the virtual router - # get the commandline from a dmistring (yes, hacky!) - dmidecode | grep cmdline | sed 's/^.*cmdline://' > $CMDLINE - RV=$? - if [ $RV -ne 0 ] ; then - log_it "Failed to get cmdline from a virtualbox dmi property" - fi - ;; - esac - - # Find and export guest type - export TYPE=$(grep -Po 'type=\K[a-zA-Z]*' $CMDLINE) -} - patch_systemvm() { local patchfile=$1 local backupfolder="/tmp/.conf.backup" @@ -158,6 +40,8 @@ patch_systemvm() { fi rm /usr/local/cloud/systemvm -rf mkdir -p /usr/local/cloud/systemvm + ls -lrt $patchfile + echo "All" | unzip $patchfile -d /usr/local/cloud/systemvm >$logfile 2>&1 find /usr/local/cloud/systemvm/ -name \*.sh | xargs chmod 555 if [ -f $backupfolder/cloud.jks ]; then @@ -171,7 +55,7 @@ patch_systemvm() { } patch() { - local PATCH_MOUNT=/media/cdrom + local PATCH_MOUNT=/home/cloud local logfile="/var/log/patchsystemvm.log" if [ "$TYPE" == "consoleproxy" ] || [ "$TYPE" == "secstorage" ] && [ -f ${PATCH_MOUNT}/agent.zip ] && [ -f /var/cache/cloud/patch.required ] @@ -188,11 +72,7 @@ patch() { rm -f /var/cache/cloud/patch.required chmod -x /etc/systemd/system/cloud*.service systemctl daemon-reload - umount $PATCH_MOUNT || true - if [ -f /mnt/cmdline ]; then - cat /mnt/cmdline > $CMDLINE - fi return 0 } @@ -212,11 +92,7 @@ config_sysctl() { bootstrap() { log_it "Bootstrapping systemvm appliance" - export HYPERVISOR=$(hypervisor) - [ $? -ne 0 ] && log_it "Failed to detect hypervisor type, bailing out" && exit 10 - log_it "Starting guest services for $HYPERVISOR" - - config_guest + export TYPE=$(grep -Po 'type=\K[a-zA-Z]*' $CMDLINE) patch config_sysctl diff --git a/systemvm/debian/opt/cloud/bin/setup/cksnode.sh b/systemvm/debian/opt/cloud/bin/setup/cksnode.sh index a864d188d009..612fdd477e8f 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cksnode.sh +++ b/systemvm/debian/opt/cloud/bin/setup/cksnode.sh @@ -39,7 +39,7 @@ setup_k8s_node() { log_it "Swap disabled" log_it "Setting up interfaces" - setup_common eth0 +# setup_common eth0 setup_system_rfc1918_internal log_it "Setting up entry in hosts" diff --git a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config index d0ebd0b68146..9695b18307bb 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config +++ b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config @@ -15,7 +15,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. - +set -x PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" # Clear boot up flag, it would be created by rc.local after boot up done @@ -32,53 +32,61 @@ log_it() { } patch() { - local PATCH_MOUNT=/media/cdrom + local PATCH_MOUNT=/home/cloud local patchfile=$PATCH_MOUNT/cloud-scripts.tgz local privkey=$PATCH_MOUNT/authorized_keys local md5file=/var/cache/cloud/cloud-scripts-signature local cdrom_dev= mkdir -p $PATCH_MOUNT - if [ -e /dev/xvdd ]; then - cdrom_dev=/dev/xvdd - elif [ -e /dev/cdrom ]; then - cdrom_dev=/dev/cdrom - elif [ -e /dev/cdrom1 ]; then - cdrom_dev=/dev/cdrom1 - elif [ -e /dev/cdrom2 ]; then - cdrom_dev=/dev/cdrom2 - elif [ -e /dev/cdrom3 ]; then - cdrom_dev=/dev/cdrom3 - fi - if [ -f /var/cache/cloud/authorized_keys ]; then privkey=/var/cache/cloud/authorized_keys fi - if [ -n "$cdrom_dev" ]; then - mount -o ro $cdrom_dev $PATCH_MOUNT - local oldmd5= - [ -f ${md5file} ] && oldmd5=$(cat ${md5file}) - local newmd5= - [ -f ${patchfile} ] && newmd5=$(md5sum ${patchfile} | awk '{print $1}') - log_it "Scripts checksum detected: oldmd5=$oldmd5 newmd5=$newmd5" - if [ "$oldmd5" != "$newmd5" ] && [ -f ${patchfile} ] && [ "$newmd5" != "" ] - then - tar xzf $patchfile -C / - echo ${newmd5} > ${md5file} - log_it "Patched scripts using $patchfile" - touch /var/cache/cloud/patch.required + retry=60 + local patched=false + while [ $retry -gt 0 ] + do + if [ -f $patchfile ]; then + local oldmd5= + [ -f ${md5file} ] && oldmd5=$(cat ${md5file}) + local newmd5= + [ -f ${patchfile} ] && newmd5=$(md5sum ${patchfile} | awk '{print $1}') + log_it "Scripts checksum detected: oldmd5=$oldmd5 newmd5=$newmd5" + log_it ls -lrt $PATCH_MOUNT + if [ "$oldmd5" != "$newmd5" ] && [ -f ${patchfile} ] && [ "$newmd5" != "" ] + then + tar xzf $patchfile -C / + ls -lrt /opt/cloud/bin/keystore* + echo ${newmd5} > ${md5file} + log_it "Patched scripts using $patchfile" + touch /var/cache/cloud/patch.required + fi + + if [ -f $privkey ]; then + cp -f $privkey /root/.ssh/ + chmod go-rwx /root/.ssh/authorized_keys + fi + patched=true + break fi - if [ -f $privkey ]; then - cp -f $privkey /root/.ssh/ - chmod go-rwx /root/.ssh/authorized_keys - fi - fi + sleep 2 + retry=$(($retry-1)) + log_it "Could not find patch file, retrying" + done + if [ $retry -eq 0 ] && [ "$patched" == "false" ]; then + return 2 + fi return 0 } +cleanup() { + rm -rf /home/cloud/agent.zip + rm -rf /home/cloud/cloud-scripts.tgz +} + start() { log_it "Executing cloud-early-config" @@ -99,6 +107,7 @@ start() { patch sync /opt/cloud/bin/setup/bootstrap.sh + cleanup log_it "Finished setting up systemvm" exit 0 diff --git a/systemvm/debian/opt/cloud/bin/setup/common.sh b/systemvm/debian/opt/cloud/bin/setup/common.sh index 60b88754bee3..7f3d85717791 100755 --- a/systemvm/debian/opt/cloud/bin/setup/common.sh +++ b/systemvm/debian/opt/cloud/bin/setup/common.sh @@ -15,7 +15,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. - +set -x PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" . /lib/lsb/init-functions diff --git a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh index 3f00f3da43a1..ec45b7ffc942 100755 --- a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh +++ b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh @@ -25,7 +25,6 @@ setup_console_proxy() { echo "haproxy dnsmasq apache2 nfs-common portmap" > /var/cache/cloud/disabled_svcs mkdir -p /var/log/cloud - setup_common eth0 eth1 eth2 setup_system_rfc1918_internal log_it "Setting up entry in hosts" @@ -33,17 +32,6 @@ setup_console_proxy() { public_ip=`getPublicIp` echo "$public_ip $NAME" >> /etc/hosts - log_it "Applying iptables rules" - cp /etc/iptables/iptables-consoleproxy /etc/iptables/rules.v4 - - log_it "Configuring sshd" - local hyp=$HYPERVISOR - if [ "$hyp" == "vmware" ] || [ "$hyp" == "hyperv" ]; then - setup_sshd $ETH1_IP "eth1" - else - setup_sshd $ETH0_IP "eth0" - fi - disable_rpfilter enable_fwding 0 enable_irqbalance 0 diff --git a/systemvm/debian/opt/cloud/bin/setup/dhcpsrvr.sh b/systemvm/debian/opt/cloud/bin/setup/dhcpsrvr.sh index 9161aeb37ee4..0b9e8a7c5cc6 100755 --- a/systemvm/debian/opt/cloud/bin/setup/dhcpsrvr.sh +++ b/systemvm/debian/opt/cloud/bin/setup/dhcpsrvr.sh @@ -25,7 +25,7 @@ dhcpsrvr_svcs() { setup_dhcpsrvr() { log_it "Setting up dhcp server system vm" - setup_common eth0 eth1 +# setup_common eth0 eth1 setup_dnsmasq setup_apache2 $ETH0_IP @@ -36,18 +36,16 @@ setup_dhcpsrvr() { enable_irqbalance 0 enable_fwding 0 - cp /etc/iptables/iptables-router /etc/iptables/rules.v4 - #Only allow DNS service for current network sed -i "s/-A INPUT -i eth0 -p udp -m udp --dport 53 -j ACCEPT/-A INPUT -i eth0 -p udp -m udp --dport 53 -s $DHCP_RANGE\/$CIDR_SIZE -j ACCEPT/g" /etc/iptables/rules.v4 sed -i "s/-A INPUT -i eth0 -p tcp -m tcp --dport 53 -j ACCEPT/-A INPUT -i eth0 -p tcp -m tcp --dport 53 -s $DHCP_RANGE\/$CIDR_SIZE -j ACCEPT/g" /etc/iptables/rules.v4 - if [ "$SSHONGUEST" == "true" ] - then - setup_sshd $ETH0_IP "eth0" - else - setup_sshd $ETH1_IP "eth1" - fi +# if [ "$SSHONGUEST" == "true" ] +# then +# setup_sshd $ETH0_IP "eth0" +# else +# setup_sshd $ETH1_IP "eth1" +# fi } dhcpsrvr_svcs diff --git a/systemvm/debian/opt/cloud/bin/setup/elbvm.sh b/systemvm/debian/opt/cloud/bin/setup/elbvm.sh index ae16b4bcb7c4..52132ccea96f 100755 --- a/systemvm/debian/opt/cloud/bin/setup/elbvm.sh +++ b/systemvm/debian/opt/cloud/bin/setup/elbvm.sh @@ -25,20 +25,11 @@ elbvm_svcs() { setup_elbvm() { log_it "Setting up Elastic Load Balancer system vm" - setup_common eth0 eth1 sed -i /$NAME/d /etc/hosts public_ip=$ETH2_IP [ "$ETH2_IP" == "0.0.0.0" ] || [ "$ETH2_IP" == "" ] && public_ip=$ETH0_IP echo "$public_ip $NAME" >> /etc/hosts - cp /etc/iptables/iptables-elbvm /etc/iptables/rules.v4 - if [ "$SSHONGUEST" == "true" ] - then - setup_sshd $ETH0_IP "eth0" - else - setup_sshd $ETH1_IP "eth1" - fi - enable_fwding 0 enable_irqbalance 0 } diff --git a/systemvm/debian/opt/cloud/bin/setup/ilbvm.sh b/systemvm/debian/opt/cloud/bin/setup/ilbvm.sh index ac801b200e6a..83cc85525d5a 100755 --- a/systemvm/debian/opt/cloud/bin/setup/ilbvm.sh +++ b/systemvm/debian/opt/cloud/bin/setup/ilbvm.sh @@ -25,7 +25,7 @@ ilbvm_svcs() { setup_ilbvm() { log_it "Setting up Internal Load Balancer system vm" - setup_common eth0 eth1 +# setup_common eth0 eth1 #eth0 = guest network, eth1=control network sed -i /$NAME/d /etc/hosts diff --git a/systemvm/debian/opt/cloud/bin/setup/init.sh b/systemvm/debian/opt/cloud/bin/setup/init.sh new file mode 100644 index 000000000000..5923b351d1c2 --- /dev/null +++ b/systemvm/debian/opt/cloud/bin/setup/init.sh @@ -0,0 +1,217 @@ +#!/bin/bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +set -x +PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" +CMDLINE=/var/cache/cloud/cmdline + +hypervisor() { + if [ -d /proc/xen ]; then + mount -t xenfs none /proc/xen + $(dmesg | grep -q "Xen HVM") + if [ $? -eq 0 ]; then # 1=PV,0=HVM + echo "xen-hvm" && return 0 + else + echo "xen-pv" && return 0 + fi + fi + + [ -x /usr/sbin/virt-what ] && local facts=( $(virt-what) ) + if [ "$facts" != "" ]; then + # Xen HVM is recognized as Hyperv when Viridian extensions are enabled + if [ "${facts[-1]}" == "xen-domU" ] && [ "${facts[0]}" == "hyperv" ]; then + echo "xen-hvm" && return 0 + else + echo ${facts[-1]} && return 0 + fi + fi + + grep -q QEMU /proc/cpuinfo && echo "kvm" && return 0 + grep -q QEMU /var/log/messages && echo "kvm" && return 0 + + vmware-checkvm &> /dev/null && echo "vmware" && return 0 + + echo "unknown" && return 1 +} + +config_guest() { + [ ! -d /proc/xen ] && sed -i 's/^vc/#vc/' /etc/inittab && telinit q + [ -d /proc/xen ] && sed -i 's/^#vc/vc/' /etc/inittab && telinit q + + systemctl daemon-reload + + case $HYPERVISOR in + xen-pv|xen-domU) + systemctl stop ntpd + systemctl disable ntpd + systemctl enable xe-daemon + systemctl start xe-daemon + + cat /proc/cmdline > $CMDLINE + sed -i "s/%/ /g" $CMDLINE + ;; + xen-hvm) + systemctl stop ntpd + systemctl disable ntpd + systemctl enable xe-daemon + systemctl start xe-daemon + + if [ ! -f /usr/bin/xenstore-read ]; then + log_it "ERROR: xentools not installed, cannot found xenstore-read" && exit 5 + fi + /usr/bin/xenstore-read vm-data/cloudstack/init > $CMDLINE + sed -i "s/%/ /g" $CMDLINE + ;; + kvm) + # Configure kvm hotplug support + if grep -E 'CONFIG_HOTPLUG_PCI=y|CONFIG_HOTPLUG_PCI_ACPI=y' /boot/config-`uname -r`; then + log_it "acpiphp and pci_hotplug module already compiled in" + else + modprobe acpiphp 2> /dev/null && log_it "acpiphp module loaded" || true + modprobe pci_hotplug 2> /dev/null && log_it "pci_hotplug module loaded" || true + fi + + sed -i -e "/^s0:2345:respawn.*/d" /etc/inittab + sed -i -e "/6:23:respawn/a\s0:2345:respawn:/sbin/getty -L 115200 ttyS0 vt102" /etc/inittab + systemctl enable qemu-guest-agent + systemctl start qemu-guest-agent + + # Wait for $CMDLINE file to be written by the qemu-guest-agent + for i in {1..60}; do + if [ -s $CMDLINE ]; then + log_it "Received a new non-empty cmdline file from qemu-guest-agent" + # Remove old configuration files in /etc/cloudstack if VR is booted from cloudstack + rm -rf /etc/cloudstack/*.json + log_it "Booting from cloudstack, remove old configuration files in /etc/cloudstack/" + break + fi + sleep 1 + done + if [ ! -s $CMDLINE ]; then + log_it "Failed to receive the cmdline file via the qemu-guest-agent" + fi + ;; + vmware) + # system time sync'd with host via vmware tools + systemctl stop ntpd + systemctl disable ntpd + systemctl enable open-vm-tools + systemctl start open-vm-tools + + vmtoolsd --cmd 'machine.id.get' > $CMDLINE + ;; + virtualpc|hyperv) + # Hyper-V is recognized as virtualpc hypervisor type. Boot args are passed using KVP Daemon + systemctl enable hyperv-daemons.hv-fcopy-daemon.service hyperv-daemons.hv-kvp-daemon.service hyperv-daemons.hv-vss-daemon.service + systemctl start hyperv-daemons.hv-fcopy-daemon.service hyperv-daemons.hv-kvp-daemon.service hyperv-daemons.hv-vss-daemon.service + sleep 5 + cp -f /var/opt/hyperv/.kvp_pool_0 $CMDLINE + cat /dev/null > /var/opt/hyperv/.kvp_pool_0 + ;; + virtualbox) + # Virtualbox is used to test the virtual router + # get the commandline from a dmistring (yes, hacky!) + dmidecode | grep cmdline | sed 's/^.*cmdline://' > $CMDLINE + RV=$? + if [ $RV -ne 0 ] ; then + log_it "Failed to get cmdline from a virtualbox dmi property" + fi + ;; + esac + + if [ -f /mnt/cmdline ]; then + cat /mnt/cmdline > $CMDLINE + fi + + # Find and export guest type + export TYPE=$(grep -Po 'type=\K[a-zA-Z]*' $CMDLINE) +} + +setup_interface_sshd() { + + if [ "$TYPE" != "cksnode" ]; then + log_it "Applying iptables rules" + if [ "$TYPE" != "dhcpsrvr" ]; then + cp /etc/iptables/iptables-$TYPE /etc/iptables/rules.v4 + else + cp /etc/iptables/iptables-router /etc/iptables/rules.v4 + fi + fi + + if [ "$TYPE" == "consoleproxy" ] || [ "$TYPE" == "secstorage" ]; then + setup_common eth0 eth1 eth2 + log_it "Configuring sshd" + local hyp=$HYPERVISOR + if [ "$hyp" == "vmware" ] || [ "$hyp" == "hyperv" ]; then + setup_sshd $ETH1_IP "eth1" + else + setup_sshd $ETH0_IP "eth0" + fi + + elif [ "$TYPE" == "router" ]; then + if [ -n "$ETH2_IP" ]; then + setup_common eth0 eth1 eth2 + + if [ -n "$EXTRA_PUBNICS" ]; then + for ((i = 3; i < 3 + $EXTRA_PUBNICS; i++)); do + setup_interface "$i" "0.0.0.0" "255.255.255.255" $GW "force" + done + fi + else + setup_common eth0 eth1 + if [ -n "$EXTRA_PUBNICS" ]; then + for ((i = 2; i < 2 + $EXTRA_PUBNICS; i++)); do + setup_interface "$i" "0.0.0.0" "255.255.255.255" $GW "force" + done + fi + fi + setup_sshd $ETH1_IP "eth1" + + elif [ "$TYPE" == "vpcrouter" ]; then + setup_interface "0" $ETH0_IP $ETH0_MASK $GW + setup_sshd $ETH0_IP "eth0" + + elif [ "$TYPE" == "ilbvm" ]; then + setup_common eth0 eth1 + setup_sshd $ETH1_IP "eth1" + + elif [ "$TYPE" == "elbvm" ] || [ "$TYPE" == "dhcpsrvr"]; then + setup_common eth0 eth1 + if [ "$SSHONGUEST" == "true" ]; then + setup_sshd $ETH0_IP "eth0" + else + setup_sshd $ETH1_IP "eth1" + fi + elif [ "$TYPE" == "cksnode" ]; then + setup_common eth0 + fi + + systemctl restart systemd-journald + # Patch known systemd/sshd memory leak - https://github.com/systemd/systemd/issues/8015#issuecomment-476160981 + echo '@include null' >> /etc/pam.d/systemd-user + # Enable and Start SSH + systemctl enable --now --no-block ssh +} + +export HYPERVISOR=$(hypervisor) +[ $? -ne 0 ] && log_it "Failed to detect hypervisor type, bailing out" && exit 10 +log_it "Starting guest services for $HYPERVISOR" + +config_guest +source /opt/cloud/bin/setup/common.sh +setup_interface_sshd \ No newline at end of file diff --git a/systemvm/debian/opt/cloud/bin/setup/postinit.sh b/systemvm/debian/opt/cloud/bin/setup/postinit.sh index 04929302f513..ba5c394d9f24 100755 --- a/systemvm/debian/opt/cloud/bin/setup/postinit.sh +++ b/systemvm/debian/opt/cloud/bin/setup/postinit.sh @@ -23,17 +23,11 @@ log_it() { log_action_msg "$@" } -# Eject cdrom if any -CMDLINE=/var/cache/cloud/cmdline -export TYPE=$(grep -Po 'type=\K[a-zA-Z]*' $CMDLINE) -if [ "$TYPE" != "cksnode" ]; then - eject || true -fi - # Restart journald for setting changes to apply systemctl restart systemd-journald -TYPE=$(grep -Po 'type=\K[a-zA-Z]*' /var/cache/cloud/cmdline) +CMDLINE=/var/cache/cloud/cmdline +TYPE=$(grep -Po 'type=\K[a-zA-Z]*' $CMDLINE) if [ "$TYPE" == "router" ] || [ "$TYPE" == "vpcrouter" ] || [ "$TYPE" == "dhcpsrvr" ] then if [ -x /opt/cloud/bin/update_config.py ] @@ -71,10 +65,4 @@ then ip6tables-restore < $ipv6 fi -# Patch known systemd/sshd memory leak - https://github.com/systemd/systemd/issues/8015#issuecomment-476160981 -echo '@include null' >> /etc/pam.d/systemd-user - -# Enable and Start SSH -systemctl enable --now --no-block ssh - date > /var/cache/cloud/boot_up_done diff --git a/systemvm/debian/opt/cloud/bin/setup/router.sh b/systemvm/debian/opt/cloud/bin/setup/router.sh index e8f6edf0ceb5..d7113c493028 100755 --- a/systemvm/debian/opt/cloud/bin/setup/router.sh +++ b/systemvm/debian/opt/cloud/bin/setup/router.sh @@ -43,23 +43,6 @@ setup_router() { oldmd5= [ -f "/etc/udev/rules.d/70-persistent-net.rules" ] && oldmd5=$(md5sum "/etc/udev/rules.d/70-persistent-net.rules" | awk '{print $1}') - if [ -n "$ETH2_IP" ]; then - setup_common eth0 eth1 eth2 - - if [ -n "$EXTRA_PUBNICS" ]; then - for ((i = 3; i < 3 + $EXTRA_PUBNICS; i++)); do - setup_interface "$i" "0.0.0.0" "255.255.255.255" $GW "force" - done - fi - else - setup_common eth0 eth1 - if [ -n "$EXTRA_PUBNICS" ]; then - for ((i = 2; i < 2 + $EXTRA_PUBNICS; i++)); do - setup_interface "$i" "0.0.0.0" "255.255.255.255" $GW "force" - done - fi - fi - log_it "Checking udev NIC assignment order changes" if [ "$NIC_MACS" != "" ] then @@ -88,8 +71,6 @@ setup_router() { enable_fwding 1 enable_rpsrfs 1 enable_passive_ftp 1 - cp /etc/iptables/iptables-router /etc/iptables/rules.v4 - setup_sshd $ETH1_IP "eth1" # Only allow DNS service for current network sed -i "s/-A INPUT -i eth0 -p udp -m udp --dport 53 -j ACCEPT/-A INPUT -i eth0 -p udp -m udp --dport 53 -s $DHCP_RANGE\/$CIDR_SIZE -j ACCEPT/g" /etc/iptables/rules.v4 diff --git a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh index 13ed5c5d0ae0..3b21ed5cae17 100755 --- a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh +++ b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh @@ -25,7 +25,6 @@ setup_secstorage() { echo "conntrackd keepalived haproxy dnsmasq" > /var/cache/cloud/disabled_svcs mkdir -p /var/log/cloud - setup_common eth0 eth1 eth2 setup_storage_network setup_system_rfc1918_internal @@ -37,14 +36,6 @@ setup_secstorage() { log_it "Applying iptables rules" cp /etc/iptables/iptables-secstorage /etc/iptables/rules.v4 - log_it "Configuring sshd" - local hyp=$HYPERVISOR - if [ "$hyp" == "vmware" ] || [ "$hyp" == "hyperv" ]; then - setup_sshd $ETH1_IP "eth1" - else - setup_sshd $ETH0_IP "eth0" - fi - log_it "Configuring apache2" setup_apache2 $ETH2_IP diff --git a/systemvm/debian/opt/cloud/bin/setup/vpcrouter.sh b/systemvm/debian/opt/cloud/bin/setup/vpcrouter.sh index f97fb161f47f..ba4af90d9b6c 100755 --- a/systemvm/debian/opt/cloud/bin/setup/vpcrouter.sh +++ b/systemvm/debian/opt/cloud/bin/setup/vpcrouter.sh @@ -29,7 +29,6 @@ setup_vpcrouter() { auto lo eth0 iface lo inet loopback EOF - setup_interface "0" $ETH0_IP $ETH0_MASK $GW echo $NAME > /etc/hostname echo 'AVAHI_DAEMON_DETECT_LOCAL=0' > /etc/default/avahi-daemon @@ -86,7 +85,7 @@ EOF enable_fwding 1 enable_passive_ftp 1 cp /etc/iptables/iptables-vpcrouter /etc/iptables/rules.v4 - setup_sshd $ETH0_IP "eth0" +# setup_sshd $ETH0_IP "eth0" cp /etc/vpcdnsmasq.conf /etc/dnsmasq.conf cp /etc/cloud-nic.rules /etc/udev/rules.d/cloud-nic.rules echo "" > /etc/dnsmasq.d/dhcphosts.txt diff --git a/systemvm/patch-sysvms.sh b/systemvm/patch-sysvms.sh new file mode 100644 index 000000000000..cf0b452f82ed --- /dev/null +++ b/systemvm/patch-sysvms.sh @@ -0,0 +1,108 @@ +#!/bin/bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" +backupfolder=/tmp/bkpup_live_patch +logfile="/var/log/livepatchsystemvm.log" +newpath="/home/cloud/" +CMDLINE=/var/cache/cloud/cmdline +md5file=/var/cache/cloud/cloud-scripts-signature +svcfile=/var/cache/cloud/enabled_svcs +TYPE=$(grep -Po 'type=\K[a-zA-Z]*' $CMDLINE) +patchfailed=0 + + +backup_old_package() { + mkdir -p $backupfolder + echo "Backing up keystore file and certificates" > $logfile + mkdir -p $backupfolder/conf + cp -r /usr/local/cloud/systemvm/conf/* $backupfolder/conf + echo "Backing up agent package" >> $logfile + zip -r $backupfolder/agent.zip /usr/local/cloud/systemvm/* >> $logfile 2>&1 + cp $md5file $backupfolder + echo "Backing up cloud-scripts file" >> $logfile + tar -zcvf $backupfolder/cloud-scripts.tgz /etc/ /var/ /opt/ /root/ >> $logfile 2>&1 +} + +restore_backup() { + echo "Restoring cloud scripts" >> $logfile + tar -xvf $backupfolder/cloud-scripts.tar -C / >> $logfile 2>&1 + echo "Restoring agent package" >> $logfile + unzip $backupfolder/agent.zip -d /usr/local/cloud/systemvm/ >> $logfile 2>&1 + echo "Restore keystore file and certificates" + mkdir -p "/usr/local/cloud/systemvm/conf/" + cp -r $backupfolder/conf/* /usr/local/cloud/systemvm/conf/ + restart_services + cp $backupfolder/cloud-scripts-signature $md5file +} + +update_checksum() { + newmd5=$(md5sum $1 | awk '{print $1}') + echo "checksum: " ${newmd5} >> $logfile + echo ${newmd5} > ${md5file} +} + +restart_services() { + systemctl daemon-reload + while IFS= read -r line + do + echo "$line" + systemctl restart "$line" + sleep 5 + systemctl is-active --quiet "$line" + if [ $? -gt 0 ]; then + echo "Failed to start "$line" service. Patch Failed. Restoring backup" >> $logfile + restore_backup + patchfailed=1 + break + fi + done < "$svcfile" +} + +cleanup_systemVM() { + rm -rf $backupfolder + rm -rf "$newpath""cloud-scripts.tgz" "$newpath""agent.zip" "$newpath""patch-sysvms.sh" +} + +patch_systemvm() { + rm -rf /usr/local/cloud/systemvm + mkdir -p /usr/local/cloud/systemvm + echo "All" | unzip $newpath/agent.zip -d /usr/local/cloud/systemvm >> $logfile 2>&1 + find /usr/local/cloud/systemvm/ -name \*.sh | xargs chmod 555 + + echo "Extracting cloud scripts" >> $logfile + tar -xvf $newpath/cloud-scripts.tgz -C / >> $logfile 2>&1 + + if [ -f $backupfolder/conf/cloud.jks ]; then + cp -r $backupfolder/conf/* /usr/local/cloud/systemvm/conf/ + echo "Restored keystore file and certs using backup" >> $logfile + fi + + update_checksum $newpath/cloud-scripts.tgz + + if [ "$TYPE" == "consoleproxy" ] || [ "$TYPE" == "secstorage" ] || [[ "$TYPE" == *router ]]; then + restart_services + fi +} + + +backup_old_package +patch_systemvm +cleanup_systemVM + +exit $patchfailed diff --git a/systemvm/pom.xml b/systemvm/pom.xml index 7fe4ae8a5e4e..929f948abd1d 100644 --- a/systemvm/pom.xml +++ b/systemvm/pom.xml @@ -88,6 +88,12 @@ agent.zip + + ${basedir} + + patch-sysvms.sh + + diff --git a/tools/appliance/build.sh b/tools/appliance/build.sh index 1c83f9aba510..79de31a9adeb 100755 --- a/tools/appliance/build.sh +++ b/tools/appliance/build.sh @@ -349,10 +349,10 @@ function main() { # process the disk at dist kvm_export - ovm_export - xen_server_export - vmware_export - hyperv_export +# ovm_export +# xen_server_export +# vmware_export +# hyperv_export rm -f "dist/${appliance}" cd dist && chmod +r * && cd .. cd dist && md5sum * > md5sum.txt && cd .. diff --git a/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh b/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh index db3eec5cb40c..8cdfce787534 100644 --- a/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh +++ b/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh @@ -68,6 +68,7 @@ function install_cloud_scripts() { chmod -x /etc/systemd/system/* || true systemctl daemon-reload + systemctl enable cloud-preinit systemctl enable cloud-early-config systemctl enable cloud-postinit } diff --git a/tools/appliance/systemvmtemplate/template.json b/tools/appliance/systemvmtemplate/template.json index bd932bf6cdef..46fdbc90a750 100644 --- a/tools/appliance/systemvmtemplate/template.json +++ b/tools/appliance/systemvmtemplate/template.json @@ -27,8 +27,8 @@ "format": "qcow2", "headless": true, "http_directory": "http", - "iso_checksum": "sha512:5f6aed67b159d7ccc1a90df33cc8a314aa278728a6f50707ebf10c02e46664e383ca5fa19163b0a1c6a4cb77a39587881584b00b45f512b4a470f1138eaa1801", - "iso_url": "https://cdimage.debian.org/debian-cd/11.0.0/amd64/iso-cd/debian-11.0.0-amd64-netinst.iso", + "iso_checksum": "sha512:02257c3ec27e45d9f022c181a69b59da67e5c72871cdb4f9a69db323a1fad58093f2e69702d29aa98f5f65e920e0b970d816475a5a936e1f3bf33832257b7e92", + "iso_url": "https://cdimage.debian.org/debian-cd/11.1.0/amd64/iso-cd/debian-11.1.0-amd64-netinst.iso", "net_device": "virtio-net", "output_directory": "../dist", "qemuargs": [ diff --git a/utils/src/main/java/com/cloud/utils/EncryptionUtil.java b/utils/src/main/java/com/cloud/utils/EncryptionUtil.java index b82842e947b6..ff791a3f5226 100644 --- a/utils/src/main/java/com/cloud/utils/EncryptionUtil.java +++ b/utils/src/main/java/com/cloud/utils/EncryptionUtil.java @@ -18,7 +18,12 @@ */ package com.cloud.utils; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.io.UnsupportedEncodingException; +import java.nio.file.Files; +import java.nio.file.Paths; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -26,6 +31,7 @@ import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.digest.DigestUtils; import org.apache.log4j.Logger; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; @@ -70,4 +76,14 @@ public static String generateSignature(String data, String key) { throw new CloudRuntimeException("unable to generate signature", e); } } + + public static String calculateChecksum(File file) { + try (InputStream is = Files.newInputStream(Paths.get(file.getPath()))) { + return DigestUtils.md5Hex(is); + } catch (IOException e) { + String errMsg = "Failed to calculate template checksum"; + s_logger.error(errMsg, e); + throw new CloudRuntimeException(errMsg, e); + } + } } diff --git a/utils/src/main/java/com/cloud/utils/ssh/SshHelper.java b/utils/src/main/java/com/cloud/utils/ssh/SshHelper.java index bce61fd4629c..7a73e8675a70 100644 --- a/utils/src/main/java/com/cloud/utils/ssh/SshHelper.java +++ b/utils/src/main/java/com/cloud/utils/ssh/SshHelper.java @@ -52,6 +52,12 @@ public static void scpTo(String host, int port, String user, File pemKeyFile, St scpTo(host, port, user, pemKeyFile, password, remoteTargetDirectory, localFile, fileMode, DEFAULT_CONNECT_TIMEOUT, DEFAULT_KEX_TIMEOUT); } + public static void scpTo(String host, int port, String user, File pemKeyFile, String password, String remoteTargetDirectory, String[] localFiles, String fileMode) + throws Exception { + + scpTo(host, port, user, pemKeyFile, password, remoteTargetDirectory, localFiles, fileMode, DEFAULT_CONNECT_TIMEOUT, DEFAULT_KEX_TIMEOUT); + } + public static void scpTo(String host, int port, String user, File pemKeyFile, String password, String remoteTargetDirectory, byte[] data, String remoteFileName, String fileMode) throws Exception { @@ -118,6 +124,42 @@ public static void scpTo(String host, int port, String user, File pemKeyFile, St } } + public static void scpTo(String host, int port, String user, File pemKeyFile, String password, String remoteTargetDirectory, String[] localFiles, String fileMode, + int connectTimeoutInMs, int kexTimeoutInMs) throws Exception { + + com.trilead.ssh2.Connection conn = null; + com.trilead.ssh2.SCPClient scpClient = null; + + try { + conn = new com.trilead.ssh2.Connection(host, port); + conn.connect(null, connectTimeoutInMs, kexTimeoutInMs); + + if (pemKeyFile == null) { + if (!conn.authenticateWithPassword(user, password)) { + String msg = "Failed to authentication SSH user " + user + " on host " + host; + s_logger.error(msg); + throw new Exception(msg); + } + } else { + if (!conn.authenticateWithPublicKey(user, pemKeyFile, password)) { + String msg = "Failed to authentication SSH user " + user + " on host " + host; + s_logger.error(msg); + throw new Exception(msg); + } + } + + scpClient = conn.createSCPClient(); + + if (fileMode != null) + scpClient.put(localFiles, remoteTargetDirectory, fileMode); + else + scpClient.put(localFiles, remoteTargetDirectory); + } finally { + if (conn != null) + conn.close(); + } + } + public static void scpTo(String host, int port, String user, File pemKeyFile, String password, String remoteTargetDirectory, byte[] data, String remoteFileName, String fileMode, int connectTimeoutInMs, int kexTimeoutInMs) throws Exception { From 65a8762df3dc3b69b100e6e390e5b11c6a93de91 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Tue, 14 Dec 2021 13:16:09 +0530 Subject: [PATCH 27/68] The following commit: - refactors logic added to support SystemVM deployment on KVM - Adds support to copy specific files (required for patching) to the hosts on Xenserver - Modifies vmops method - createFileInDomr to take cleanup param - Adds configuratble sleep param to CitrixResourceBase::connect() used to verify if telnet to specifc port is possible (if sleep is 0, then default to _sleep = 10000ms) - Adds Command/Answer for patch systemVMs on XenServer/Xcp --- .../com/cloud/resource/ServerResource.java | 8 ++ .../cloud/resource/ServerResourceBase.java | 12 ++ .../resource/LibvirtComputingResource.java | 5 - .../LibvirtPatchSystemVmCommandWrapper.java | 35 +----- .../wrapper/LibvirtStartCommandWrapper.java | 12 +- .../resource/CitrixResourceBase.java | 47 ++++++-- .../xenbase/CitrixCheckSshCommandWrapper.java | 2 +- .../CitrixPatchSystemVmCommandWrapper.java | 106 ++++++++++++++++++ .../CitrixRebootRouterCommandWrapper.java | 2 +- .../xenbase/CitrixStartCommandWrapper.java | 24 ++++ scripts/vm/hypervisor/xenserver/vmops | 4 +- scripts/vm/hypervisor/xenserver/xcposs/patch | 3 + .../vm/hypervisor/xenserver/xcpserver/patch | 5 +- .../vm/hypervisor/xenserver/xenserver56/patch | 3 + .../hypervisor/xenserver/xenserver56fp1/patch | 3 + .../vm/hypervisor/xenserver/xenserver60/patch | 3 + .../vm/hypervisor/xenserver/xenserver62/patch | 3 + .../vm/hypervisor/xenserver/xenserver65/patch | 3 + tools/appliance/build.sh | 6 +- .../main/java/com/cloud/utils/FileUtil.java | 23 ++++ 20 files changed, 246 insertions(+), 63 deletions(-) create mode 100644 plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java diff --git a/core/src/main/java/com/cloud/resource/ServerResource.java b/core/src/main/java/com/cloud/resource/ServerResource.java index 16ac00ed176b..5571f33bb8a3 100644 --- a/core/src/main/java/com/cloud/resource/ServerResource.java +++ b/core/src/main/java/com/cloud/resource/ServerResource.java @@ -27,11 +27,19 @@ import com.cloud.host.Host; import com.cloud.utils.component.Manager; +import java.io.File; + /** * ServerResource is a generic container to execute commands sent */ public interface ServerResource extends Manager { + String[] srcFiles = new String[] { "agent.zip", "cloud-scripts.tgz" }; + String[] newSrcFiles = new String[] { "agent.zip", "cloud-scripts.tgz", "patch-sysvms.sh" }; + + String SSHKEYSPATH = "/root/.ssh"; + String SSHPRVKEYPATH = SSHKEYSPATH + File.separator + "id_rsa.cloud"; + /** * @return Host.Type type of the computing server we have. */ diff --git a/core/src/main/java/com/cloud/resource/ServerResourceBase.java b/core/src/main/java/com/cloud/resource/ServerResourceBase.java index f68bcf409ef3..80057779e249 100644 --- a/core/src/main/java/com/cloud/resource/ServerResourceBase.java +++ b/core/src/main/java/com/cloud/resource/ServerResourceBase.java @@ -19,6 +19,7 @@ package com.cloud.resource; +import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; import java.net.NetworkInterface; @@ -32,6 +33,8 @@ import javax.naming.ConfigurationException; +import com.cloud.utils.EncryptionUtil; +import com.cloud.utils.exception.CloudRuntimeException; import org.apache.log4j.Logger; import com.cloud.agent.IAgentControl; @@ -306,4 +309,13 @@ public boolean start() { public boolean stop() { return true; } + + public String calculateCurrentChecksum(String name) { + String cloudScriptsPath = Script.findScript("", "vms/cloud-scripts.tgz"); + if (cloudScriptsPath == null) { + throw new CloudRuntimeException(String.format("Unable to find cloudScripts path, cannot update SystemVM %s", name)); + } + String md5sum = EncryptionUtil.calculateChecksum(new File(cloudScriptsPath)); + return md5sum; + } } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index a3257f9967bd..e7cdfbb925f7 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -281,9 +281,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv public static final String RESIZE_NOTIFY_ONLY = "NOTIFYONLY"; public static final String BASEPATH = "/usr/share/cloudstack-common/vms/"; - public static String[] srcFiles = new String[] { "agent.zip", "cloud-scripts.tgz" }; - public static String[] newSrcFiles = new String[] { "agent.zip", "cloud-scripts.tgz", "patch-sysvms.sh" }; - private String _modifyVlanPath; private String _versionstringpath; private String _patchScriptPath; @@ -309,8 +306,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv private static final int NUMMEMSTATS =2; private KVMHAMonitor _monitor; - public static final String SSHKEYSPATH = "/root/.ssh"; - public static final String SSHPRVKEYPATH = SSHKEYSPATH + File.separator + "id_rsa.cloud"; public static final String SSHPUBKEYPATH = SSHKEYSPATH + File.separator + "id_rsa.pub.cloud"; public static final String DEFAULTDOMRSSHPORT = "3922"; diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java index 392ccb6e6584..5fac33ebec22 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java @@ -24,19 +24,15 @@ import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource; import com.cloud.resource.CommandWrapper; import com.cloud.resource.ResourceWrapper; -import com.cloud.utils.EncryptionUtil; import com.cloud.utils.ExecutionResult; +import com.cloud.utils.FileUtil; import com.cloud.utils.Pair; import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.script.Script; import com.cloud.utils.ssh.SshHelper; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import java.io.File; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; @ResourceWrapper(handles = PatchSystemVmCommand.class) public class LibvirtPatchSystemVmCommandWrapper extends CommandWrapper { @@ -51,7 +47,7 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR ExecutionResult result; try { result = getSystemVmVersionAndChecksum(serverResource, controlIp); - scpPatchFiles(controlIp); + FileUtil.scpPatchFiles(controlIp, "/home/cloud", sshPort, pemFile, serverResource.newSrcFiles, LibvirtComputingResource.BASEPATH); } catch (CloudRuntimeException e) { return new PatchSystemVmAnswer(cmd, e.getMessage()); } @@ -63,7 +59,7 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR } String scriptChecksum = lines[1].trim(); - String checksum = calculateCurrentChecksum(sysVMName).trim(); + String checksum = serverResource.calculateCurrentChecksum(sysVMName).trim(); if (!StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum)) { if (!cmd.isForced()) { @@ -87,15 +83,6 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR return new PatchSystemVmAnswer(cmd, patchResult.second()); } - private String calculateCurrentChecksum(String name) { - String cloudScriptsPath = Script.findScript("", "vms/cloud-scripts.tgz"); - if (cloudScriptsPath == null) { - throw new CloudRuntimeException(String.format("Unable to find cloudScripts path, cannot update SystemVM %s", name)); - } - String md5sum = EncryptionUtil.calculateChecksum(new File(cloudScriptsPath)); - return md5sum; - } - private ExecutionResult getSystemVmVersionAndChecksum(LibvirtComputingResource serverResource, String controlIp) { ExecutionResult result; try { @@ -112,21 +99,5 @@ private ExecutionResult getSystemVmVersionAndChecksum(LibvirtComputingResource s } return result; } - - private void scpPatchFiles(String controlIp) { - try { - List srcFiles = Arrays.asList(LibvirtComputingResource.newSrcFiles); - srcFiles = srcFiles.stream() - .map(file -> LibvirtComputingResource.BASEPATH + file) // Using Lambda notation to update the entries - .collect(Collectors.toList()); - String[] newSrcFiles = srcFiles.toArray(new String[0]); - SshHelper.scpTo(controlIp, sshPort, "root", pemFile, null, - "/home/cloud/", newSrcFiles, "0755"); - } catch (Exception e) { - String errMsg = "Failed to scp files to system VM"; - s_logger.error(errMsg, e); - throw new CloudRuntimeException(errMsg, e); - } - } } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java index b95c163e7081..2ac8bf798482 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java @@ -21,11 +21,8 @@ import java.io.File; import java.net.URISyntaxException; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; -import com.cloud.utils.ssh.SshHelper; +import com.cloud.utils.FileUtil; import org.apache.log4j.Logger; import org.libvirt.Connect; import org.libvirt.DomainInfo.DomainState; @@ -122,13 +119,8 @@ public Answer execute(final StartCommand command, final LibvirtComputingResource } try { - List srcFiles = Arrays.asList(LibvirtComputingResource.srcFiles); - srcFiles = srcFiles.stream() - .map(file -> LibvirtComputingResource.BASEPATH + file) - .collect(Collectors.toList()); File pemFile = new File(LibvirtComputingResource.SSHPRVKEYPATH); - SshHelper.scpTo(controlIp, 3922, "root", pemFile, null, - "/home/cloud/", srcFiles.toArray(new String[0]), "0755"); + FileUtil.scpPatchFiles(controlIp, "/home/cloud", Integer.parseInt(LibvirtComputingResource.DEFAULTDOMRSSHPORT), pemFile, LibvirtComputingResource.newSrcFiles, LibvirtComputingResource.BASEPATH); // TODO: May want to remove this when cert patching logic is moved Thread.sleep(10000); } catch (Exception e) { diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java index fffbd800412e..117ad3b1cdc7 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java @@ -52,6 +52,7 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import com.cloud.resource.ServerResourceBase; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.diagnostics.CopyToSecondaryStorageAnswer; import org.apache.cloudstack.diagnostics.CopyToSecondaryStorageCommand; @@ -180,7 +181,7 @@ * before you do any changes in this code here. * */ -public abstract class CitrixResourceBase implements ServerResource, HypervisorResource, VirtualRouterDeployer { +public abstract class CitrixResourceBase extends ServerResourceBase implements ServerResource, HypervisorResource, VirtualRouterDeployer { /** * used to describe what type of resource a storage device is of */ @@ -216,6 +217,7 @@ public String toString() { private final static String VM_NAME_ISO_SUFFIX = "-ISO"; private final static String VM_FILE_ISO_SUFFIX = ".iso"; + public final static int DEFAULTDOMRSSHPORT = 3922; private static final XenServerConnectionPool ConnPool = XenServerConnectionPool.getInstance(); // static min values for guests on xenserver @@ -226,8 +228,11 @@ public String toString() { protected static final HashMap s_powerStatesTable; public static final String XS_TOOLS_ISO_AFTER_70 = "guest-tools.iso"; + protected static final String PLATFORM_CORES_PER_SOCKET_KEY = "cores-per-socket"; + public static final String BASEPATH = "/opt/xensource/packages/resources/"; + static { s_powerStatesTable = new HashMap(); s_powerStatesTable.put(VmPowerState.HALTED, PowerState.PowerOff); @@ -340,6 +345,11 @@ protected StorageSubsystemCommandHandler buildStorageHandler() { return new StorageSubsystemCommandHandlerBase(processor); } + @Override + protected String getDefaultScriptsDir() { + return null; + } + public String callHostPlugin(final Connection conn, final String plugin, final String cmd, final String... params) { final Map args = new HashMap(); String msg; @@ -905,11 +915,15 @@ public synchronized Network configureTunnelNetwork(final Connection conn, final } } - public String connect(final Connection conn, final String vmname, final String ipAddress) { - return connect(conn, vmname, ipAddress, 3922); + public String connect(final Connection conn, final String vmname, final String ipAddress, int sleep) { + return connect(conn, vmname, ipAddress, DEFAULTDOMRSSHPORT, sleep); } - public String connect(final Connection conn, final String vmName, final String ipAddress, final int port) { + public String connect(final Connection conn, final String vmName, final String ipAddress, final int port, int sleep) { + if (sleep == 0) { + sleep = _sleep; + } + for (int i = 0; i <= _retry; i++) { try { final Set vms = VM.getByNameLabel(conn, vmName); @@ -930,7 +944,7 @@ public String connect(final Connection conn, final String vmName, final String i return null; } try { - Thread.sleep(_sleep); + Thread.sleep(sleep); } catch (final InterruptedException e) { } } @@ -975,8 +989,25 @@ public ExecutionResult createFileInVR(final String routerIp, final String path, s_logger.warn("scp VR config file into host " + _host.getIp() + " failed with exception " + e.getMessage().toString()); } - final String rc = callHostPlugin(conn, "vmops", "createFileInDomr", "domrip", routerIp, "srcfilepath", hostPath + filename, "dstfilepath", path); - s_logger.debug("VR Config file " + filename + " got created in VR, ip " + routerIp + " with content \n" + content); + final String rc = callHostPlugin(conn, "vmops", "createFileInDomr", "domrip", routerIp, "srcfilepath", hostPath + filename, "dstfilepath", path, "cleanup", "true"); + s_logger.debug("VR Config file " + filename + " got created in VR, IP: " + routerIp + " with content \n" + content); + + return new ExecutionResult(rc.startsWith("succ#"), rc.substring(5)); + } + + public ExecutionResult copyPatchFilesToVR(final String routerIp, final String path) { + final Connection conn = getConnection(); + final String hostPath = "/opt/xensource/packages/resources/"; + String rc = ""; + for (String file: newSrcFiles) { + rc = callHostPlugin(conn, "vmops", "createFileInDomr", "domrip", routerIp, "srcfilepath", hostPath.concat(file), "dstfilepath", path, "cleanup", "false"); + if (rc.startsWith("fail#")) { + s_logger.error(String.format("Failed to scp file %s required for patching the systemVM", file)); + break; + } + } + + s_logger.debug("VR Config files at " + hostPath + " got created in VR, IP: " + routerIp); return new ExecutionResult(rc.startsWith("succ#"), rc.substring(5)); } @@ -4897,7 +4928,7 @@ public boolean setupServer(final Connection conn, final Host host) { throw new CloudRuntimeException("Unable to authenticate"); } - final String cmd = "mkdir -p /opt/cloud/bin /var/log/cloud"; + final String cmd = "mkdir -p /opt/cloud/bin /var/log/cloud /opt/xensource/packages/resources/"; if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) { throw new CloudRuntimeException("Cannot create directory /opt/cloud/bin on XenServer hosts"); } diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixCheckSshCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixCheckSshCommandWrapper.java index cf34a8fb30cd..ec7d844dfbc7 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixCheckSshCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixCheckSshCommandWrapper.java @@ -46,7 +46,7 @@ public Answer execute(final CheckSshCommand command, final CitrixResourceBase ci } try { - final String result = citrixResourceBase.connect(conn, command.getName(), privateIp, cmdPort); + final String result = citrixResourceBase.connect(conn, command.getName(), privateIp, cmdPort, 0); if (result != null) { return new CheckSshAnswer(command, "Can not ping System vm " + vmName + "due to:" + result); } diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java new file mode 100644 index 000000000000..e27381e694da --- /dev/null +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java @@ -0,0 +1,106 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.hypervisor.xenserver.resource.wrapper.xenbase; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.PatchSystemVmAnswer; +import com.cloud.agent.api.PatchSystemVmCommand; +import com.cloud.agent.api.routing.NetworkElementCommand; +import com.cloud.agent.resource.virtualnetwork.VRScripts; +import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; +import com.cloud.resource.CommandWrapper; +import com.cloud.resource.ResourceWrapper; +import com.cloud.utils.ExecutionResult; +import com.cloud.utils.FileUtil; +import com.cloud.utils.Pair; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.ssh.SshHelper; +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Logger; + +import java.io.File; + +@ResourceWrapper(handles = PatchSystemVmCommand.class) +public class CitrixPatchSystemVmCommandWrapper extends CommandWrapper { + private static final Logger s_logger = Logger.getLogger(CitrixPatchSystemVmCommandWrapper.class); + private static int sshPort = CitrixResourceBase.DEFAULTDOMRSSHPORT; + private static File pemFile = new File(CitrixResourceBase.SSHPRVKEYPATH); + + @Override + public Answer execute(PatchSystemVmCommand command, CitrixResourceBase serverResource) { + final String controlIp = command.getAccessDetail(NetworkElementCommand.ROUTER_IP); + final String sysVMName = command.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + + + ExecutionResult result; + try { + result = getSystemVmVersionAndChecksum(serverResource, controlIp); + FileUtil.scpPatchFiles(controlIp, "/home/cloud", sshPort, pemFile, serverResource.newSrcFiles, CitrixResourceBase.BASEPATH); + } catch (CloudRuntimeException e) { + return new PatchSystemVmAnswer(command, e.getMessage()); + } + + final String[] lines = result.getDetails().split("&"); + // TODO: do we fail, or patch anyway?? + if (lines.length != 2) { + return new PatchSystemVmAnswer(command, result.getDetails()); + } + + String scriptChecksum = lines[1].trim(); + String checksum = serverResource.calculateCurrentChecksum(sysVMName).trim(); + + if (!StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum)) { + if (!command.isForced()) { + String msg = String.format("No change in the scripts checksum, not patching systemVM %s", sysVMName); + s_logger.info(msg); + return new PatchSystemVmAnswer(command, msg, lines[0], lines[1]); + } + } + Pair patchResult = null; + try { + patchResult = SshHelper.sshExecute(controlIp, sshPort, "root", + pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 60000); + } catch (Exception e) { + return new PatchSystemVmAnswer(command, e.getMessage()); + } + + if (patchResult.first()) { + return new PatchSystemVmAnswer(command, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], lines[1]); + } + return new PatchSystemVmAnswer(command, patchResult.second()); + + } + + private ExecutionResult getSystemVmVersionAndChecksum(CitrixResourceBase serverResource, String controlIp) { + ExecutionResult result; + try { + result = serverResource.executeInVR(controlIp, VRScripts.VERSION, null); + if (!result.isSuccess()) { + String errMsg = String.format("GetSystemVMVersionCmd on %s failed, message %s", controlIp, result.getDetails()); + s_logger.error(errMsg); + throw new CloudRuntimeException(errMsg); + } + } catch (final Exception e) { + final String msg = "GetSystemVMVersionCmd failed due to " + e; + s_logger.error(msg, e); + throw new CloudRuntimeException(msg, e); + } + return result; + } + + +} diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixRebootRouterCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixRebootRouterCommandWrapper.java index 236d8db3858a..a87458326e5b 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixRebootRouterCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixRebootRouterCommandWrapper.java @@ -40,7 +40,7 @@ public Answer execute(final RebootRouterCommand command, final CitrixResourceBas final Answer answer = wrapper.execute(rebootCommand, citrixResourceBase); if (answer.getResult()) { - final String cnct = citrixResourceBase.connect(conn, command.getVmName(), command.getPrivateIpAddress()); + final String cnct = citrixResourceBase.connect(conn, command.getVmName(), command.getPrivateIpAddress(), 0); citrixResourceBase.networkUsage(conn, command.getPrivateIpAddress(), "create", null); if (cnct == null) { diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java index ecd1b0d718c9..f4ee77c347f3 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java @@ -25,6 +25,7 @@ import java.util.Map; import java.util.Set; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; @@ -180,6 +181,29 @@ public Answer execute(final StartCommand command, final CitrixResourceBase citri state = VmPowerState.RUNNING; + String controlIp = null; + for (final NicTO nic : vmSpec.getNics()) { + if (nic.getType() == Networks.TrafficType.Control) { + controlIp = nic.getIp(); + break; + } + } + + String result2 = citrixResourceBase.connect(conn, vmName, controlIp, 1000); + if (StringUtils.isEmpty(result2)) { + s_logger.info(String.format("Connected to SystemVM: %s", vmName)); + } + + try { + citrixResourceBase.copyPatchFilesToVR(controlIp, "/home/cloud"); + // TODO: May want to remove this when cert patching logic is moved + Thread.sleep(10000); + } catch (Exception e) { + String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; + s_logger.error(errMsg, e); + return new StartAnswer(command, String.format("%s due to: %s", errMsg, e.getMessage())); + } + final StartAnswer startAnswer = new StartAnswer(command); startAnswer.setIqnToData(iqnToData); diff --git a/scripts/vm/hypervisor/xenserver/vmops b/scripts/vm/hypervisor/xenserver/vmops index dd03ded95927..e5c7e1a37880 100755 --- a/scripts/vm/hypervisor/xenserver/vmops +++ b/scripts/vm/hypervisor/xenserver/vmops @@ -235,11 +235,13 @@ def createFileInDomr(session, args): src_filepath = args['srcfilepath'] dst_path = args['dstfilepath'] domrip = args['domrip'] + cleanup = 'true' if 'cleanup' not in args else args['cleanup'] txt="" try: target = "root@" + domrip + ":" + dst_path txt = util.pread2(['scp','-P','3922','-q','-o','StrictHostKeyChecking=no','-i','/root/.ssh/id_rsa.cloud',src_filepath, target]) - util.pread2(['rm',src_filepath]) + if cleanup == 'true' or not cleanup: + util.pread2(['rm',src_filepath]) txt = 'succ#' + txt except: logging.debug("failed to copy file " + src_filepath + " from host to VR with ip " + domrip) diff --git a/scripts/vm/hypervisor/xenserver/xcposs/patch b/scripts/vm/hypervisor/xenserver/xcposs/patch index d3c5db052458..f855c660d3ce 100644 --- a/scripts/vm/hypervisor/xenserver/xcposs/patch +++ b/scripts/vm/hypervisor/xenserver/xcposs/patch @@ -32,6 +32,9 @@ ovsgre=..,0755,/usr/lib/xcp/plugins ovstunnel=..,0755,/usr/lib/xcp/plugins vmopsSnapshot=..,0755,/usr/lib/xcp/plugins systemvm.iso=../../../../../vms,0644,/usr/share/xcp/packages/iso/ +agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ +cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ +patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin setupxenserver.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xcpserver/patch b/scripts/vm/hypervisor/xenserver/xcpserver/patch index 32c7c46728d8..9768cba296da 100644 --- a/scripts/vm/hypervisor/xenserver/xcpserver/patch +++ b/scripts/vm/hypervisor/xenserver/xcpserver/patch @@ -32,8 +32,9 @@ vmops=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso -agent.zip=../../../../../vms,0644,/opt/xensource/packages/iso -cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/iso +agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ +cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ +patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin setupxenserver.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver56/patch b/scripts/vm/hypervisor/xenserver/xenserver56/patch index b6f7cdbb5c1b..8a784ae21e64 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver56/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver56/patch @@ -31,6 +31,9 @@ vmops=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ +cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ +patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin setupxenserver.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch b/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch index 4546796f9b36..93d2e4dee6ec 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch @@ -31,6 +31,9 @@ vmops=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ +cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ +patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin setupxenserver.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver60/patch b/scripts/vm/hypervisor/xenserver/xenserver60/patch index bea0cf9bfd17..0271d06f5cf4 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver60/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver60/patch @@ -35,6 +35,9 @@ cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ +cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ +patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin setupxenserver.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver62/patch b/scripts/vm/hypervisor/xenserver/xenserver62/patch index db137c9826f3..5fda3aff5514 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver62/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver62/patch @@ -36,6 +36,9 @@ cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins cloud-plugin-storage=..,0755,/etc/xapi.d/plugins systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ +cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ +patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin setupxenserver.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver65/patch b/scripts/vm/hypervisor/xenserver/xenserver65/patch index db137c9826f3..5fda3aff5514 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver65/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver65/patch @@ -36,6 +36,9 @@ cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins cloud-plugin-storage=..,0755,/etc/xapi.d/plugins systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ +cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ +patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin setupxenserver.sh=..,0755,/opt/cloud/bin diff --git a/tools/appliance/build.sh b/tools/appliance/build.sh index 79de31a9adeb..7075c135d42d 100755 --- a/tools/appliance/build.sh +++ b/tools/appliance/build.sh @@ -349,9 +349,9 @@ function main() { # process the disk at dist kvm_export -# ovm_export -# xen_server_export -# vmware_export + ovm_export + xen_server_export + vmware_export # hyperv_export rm -f "dist/${appliance}" cd dist && chmod +r * && cd .. diff --git a/utils/src/main/java/com/cloud/utils/FileUtil.java b/utils/src/main/java/com/cloud/utils/FileUtil.java index c55dd74e21bf..2121d3a7ae26 100644 --- a/utils/src/main/java/com/cloud/utils/FileUtil.java +++ b/utils/src/main/java/com/cloud/utils/FileUtil.java @@ -21,12 +21,35 @@ import java.io.File; import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.ssh.SshHelper; import org.apache.commons.io.FileUtils; +import org.apache.log4j.Logger; public class FileUtil { + private static final Logger s_logger = Logger.getLogger(FileUtil.class); public static void copyfile(File source, File destination) throws IOException { FileUtils.copyFile(source, destination); } + + public static void scpPatchFiles(String controlIp, String destPath, int sshPort, File pemFile, String[] files, String basePath) { + try { + List srcFiles = Arrays.asList(files); + srcFiles = srcFiles.stream() + .map(file -> basePath + file) // Using Lambda notation to update the entries + .collect(Collectors.toList()); + String[] newSrcFiles = srcFiles.toArray(new String[0]); + SshHelper.scpTo(controlIp, sshPort, "root", pemFile, null, + destPath, newSrcFiles, "0755"); + } catch (Exception e) { + String errMsg = "Failed to scp files to system VM"; + s_logger.error(errMsg, e); + throw new CloudRuntimeException(errMsg, e); + } + } } From ce92de4009ddbe3a36700688414c0a2e8b4e72ba Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Tue, 14 Dec 2021 18:25:07 +0530 Subject: [PATCH 28/68] - Support to patch SystemVMs - VMWare - Remove attaching systemvm.iso to systemVMs - Modify / Refactor VMware start command to copy patch related files to the systemvms - cleanup --- .../vmware/resource/VmwareResource.java | 114 +++++++++++++++++- .../CitrixPatchSystemVmCommandWrapper.java | 19 ++- scripts/vm/hypervisor/xenserver/vmops | 16 ++- .../java/com/cloud/vm/UserVmManagerImpl.java | 2 +- 4 files changed, 136 insertions(+), 15 deletions(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 297e5344a1dc..f258f6a6f8e5 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -47,6 +47,10 @@ import javax.naming.ConfigurationException; import javax.xml.datatype.XMLGregorianCalendar; +import com.cloud.agent.api.PatchSystemVmAnswer; +import com.cloud.agent.api.PatchSystemVmCommand; +import com.cloud.resource.ServerResourceBase; +import com.cloud.utils.FileUtil; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.storage.command.CopyCommand; import org.apache.cloudstack.storage.command.StorageSubSystemCommand; @@ -360,10 +364,11 @@ import com.vmware.vim25.VmwareDistributedVirtualSwitchPvlanSpec; import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanIdSpec; -public class VmwareResource implements StoragePoolResource, ServerResource, VmwareHostService, VirtualRouterDeployer { +public class VmwareResource extends ServerResourceBase implements StoragePoolResource, ServerResource, VmwareHostService, VirtualRouterDeployer { private static final Logger s_logger = Logger.getLogger(VmwareResource.class); public static final String VMDK_EXTENSION = ".vmdk"; private static final String EXECUTING_RESOURCE_COMMAND = "Executing resource command %s: [%s]."; + public static final String BASEPATH = "/usr/share/cloudstack-common/vms/"; private static final Random RANDOM = new Random(System.nanoTime()); @@ -590,7 +595,9 @@ public Answer executeRequest(Command cmd) { answer = execute((SetupPersistentNetworkCommand) cmd); } else if (clz == GetVmVncTicketCommand.class) { answer = execute((GetVmVncTicketCommand) cmd); - } else { + } else if (clz == PatchSystemVmCommand.class) { + answer = execute((PatchSystemVmCommand) cmd); + } else { answer = Answer.createUnsupportedCommandAnswer(cmd); } @@ -630,6 +637,68 @@ public Answer executeRequest(Command cmd) { return answer; } + private ExecutionResult getSystemVmVersionAndChecksum(String controlIp) { + ExecutionResult result; + try { + result = executeInVR(controlIp, VRScripts.VERSION, null); + if (!result.isSuccess()) { + String errMsg = String.format("GetSystemVMVersionCmd on %s failed, message %s", controlIp, result.getDetails()); + s_logger.error(errMsg); + throw new CloudRuntimeException(errMsg); + } + } catch (final Exception e) { + final String msg = "GetSystemVMVersionCmd failed due to " + e; + s_logger.error(msg, e); + throw new CloudRuntimeException(msg, e); + } + return result; + } + + private Answer execute(PatchSystemVmCommand cmd) { + String controlIp = getRouterSshControlIp(cmd); + String sysVMName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + String homeDir = System.getProperty("user.home"); + File pemFile = new File(homeDir + "/.ssh/id_rsa"); + + ExecutionResult result = getSystemVmVersionAndChecksum(controlIp); + try { + FileUtil.scpPatchFiles(controlIp, "/home/cloud", DefaultDomRSshPort, pemFile, newSrcFiles, BASEPATH); + } catch (CloudRuntimeException e) { + return new PatchSystemVmAnswer(cmd, e.getMessage()); + } + + final String[] lines = result.getDetails().split("&"); + // TODO: do we fail, or patch anyway?? + if (lines.length != 2) { + return new PatchSystemVmAnswer(cmd, result.getDetails()); + } + + String scriptChecksum = lines[1].trim(); + String checksum = calculateCurrentChecksum(sysVMName).trim(); + + if (!org.apache.commons.lang3.StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum)) { + if (!cmd.isForced()) { + String msg = String.format("No change in the scripts checksum, not patching systemVM %s", sysVMName); + s_logger.info(msg); + return new PatchSystemVmAnswer(cmd, msg, lines[0], lines[1]); + } + } + + Pair patchResult = null; + try { + patchResult = SshHelper.sshExecute(controlIp, DefaultDomRSshPort, "root", + pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 60000); + } catch (Exception e) { + return new PatchSystemVmAnswer(cmd, e.getMessage()); + } + + if (patchResult.first()) { + return new PatchSystemVmAnswer(cmd, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], lines[1]); + } + return new PatchSystemVmAnswer(cmd, patchResult.second()); + + } + private Answer execute(SetupPersistentNetworkCommand cmd) { VmwareHypervisorHost host = getHyperHost(getServiceContext()); String hostname = null; @@ -2072,7 +2141,7 @@ protected StartAnswer execute(StartCommand cmd) { deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec(); Pair isoInfo = VmwareHelper.prepareIsoDevice(vmMo, - String.format("[%s] systemvm/%s", secDsMo.getName(), mgr.getSystemVMIsoFileNameOnDatastore()), secDsMo.getMor(), true, true, ideUnitNumber++, i + 1); + null, secDsMo.getMor(), true, true, ideUnitNumber++, i + 1); deviceConfigSpecArray[i].setDevice(isoInfo.first()); if (isoInfo.second()) { if (s_logger.isDebugEnabled()) @@ -2457,6 +2526,29 @@ protected StartAnswer execute(StartCommand cmd) { startAnswer.setIqnToData(iqnToData); + if (vmSpec.getType() != VirtualMachine.Type.User) { + String controlIp = getControlIp(nics); + // check if the router is up? + for (int count = 0; count < 60; count++) { + final boolean result = _vrResource.connect(controlIp, 1, 5000); + if (result) { + break; + } + } + + try { + String homeDir = System.getProperty("user.home"); + File pemFile = new File(homeDir + "/.ssh/id_rsa"); + FileUtil.scpPatchFiles(controlIp, "/home/cloud", DefaultDomRSshPort, pemFile, newSrcFiles, BASEPATH); + // TODO: May want to remove this when cert patching logic is moved + Thread.sleep(10000); + } catch (Exception e) { + String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; + s_logger.error(errMsg, e); + return new StartAnswer(cmd, String.format("%s due to: %s", errMsg, e.getMessage())); + } + } + // Since VM was successfully powered-on, if there was an existing VM in a different cluster that was unregistered, delete all the files associated with it. if (existingVmName != null && existingVmFileLayout != null) { List vmDatastoreNames = new ArrayList(); @@ -3848,6 +3940,17 @@ private String getNetworkNamePrefix(NicTO nicTo) throws Exception { } } + private String getControlIp(NicTO[] nicTOs) { + String controlIpAddress = null; + for (NicTO nic : nicTOs) { + if ((TrafficType.Management == nic.getType() || TrafficType.Control == nic.getType()) && nic.getIp() != null) { + controlIpAddress = nic.getIp(); + break; + } + } + return controlIpAddress; + } + private VirtualMachineMO takeVmFromOtherHyperHost(VmwareHypervisorHost hyperHost, String vmName) throws Exception { VirtualMachineMO vmMo = hyperHost.findVmOnPeerHyperHost(vmName); @@ -6650,6 +6753,11 @@ public String getName() { return _name; } + @Override + protected String getDefaultScriptsDir() { + return null; + } + @Override public boolean start() { return true; diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java index e27381e694da..a6b183f9d11e 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java @@ -25,10 +25,8 @@ import com.cloud.resource.CommandWrapper; import com.cloud.resource.ResourceWrapper; import com.cloud.utils.ExecutionResult; -import com.cloud.utils.FileUtil; -import com.cloud.utils.Pair; import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.ssh.SshHelper; +import com.xensource.xenapi.Connection; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; @@ -44,12 +42,13 @@ public class CitrixPatchSystemVmCommandWrapper extends CommandWrapper patchResult = null; + String patchResult = null; try { - patchResult = SshHelper.sshExecute(controlIp, sshPort, "root", - pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 60000); + patchResult = serverResource.callHostPlugin(conn, "vmops", "runPatchScriptInDomr", "domrip", controlIp); } catch (Exception e) { return new PatchSystemVmAnswer(command, e.getMessage()); } - if (patchResult.first()) { + + if (patchResult.startsWith("succ#")) { return new PatchSystemVmAnswer(command, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], lines[1]); } - return new PatchSystemVmAnswer(command, patchResult.second()); + return new PatchSystemVmAnswer(command, patchResult.substring(5)); } diff --git a/scripts/vm/hypervisor/xenserver/vmops b/scripts/vm/hypervisor/xenserver/vmops index e5c7e1a37880..cea47cce2975 100755 --- a/scripts/vm/hypervisor/xenserver/vmops +++ b/scripts/vm/hypervisor/xenserver/vmops @@ -248,6 +248,19 @@ def createFileInDomr(session, args): txt = 'fail#' + txt return txt +@echo +def runPatchScriptInDomr(session, args): + domrip = args['domrip'] + txt="" + try: + target = "root@" + domrip + txt = util.pread2(['ssh','-p','3922','-i','/root/.ssh/id_rsa.cloud', target, "/bin/bash","/home/cloud/patch-sysvms.sh"]) + txt = 'succ#' + txt + except: + logging.debug("failed to run patch script in systemVM with IP: " + domrip) + txt = 'fail#' + txt + return txt + @echo def deleteFile(session, args): file_path = args["filepath"] @@ -1590,4 +1603,5 @@ if __name__ == "__main__": "cleanup_rules":cleanup_rules, "createFileInDomr":createFileInDomr, "kill_copy_process":kill_copy_process, - "secureCopyToHost":secureCopyToHost}) + "secureCopyToHost":secureCopyToHost, + "runPatchScriptInDomr": runPatchScriptInDomr}) diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index 275f7018b40e..581995d07fcf 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -4896,7 +4896,7 @@ public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile prof } @Override - public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { + public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { UserVmVO vm = _vmDao.findById(profile.getId()); Answer[] answersToCmds = cmds.getAnswers(); From f1e71aa50c4870d8eca5354263e1a646933dd48b Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Tue, 21 Dec 2021 14:24:32 +0530 Subject: [PATCH 29/68] Commit comprises of: - remove docker from systemvm template - use containerd as container runtime - update create-k8s-binaries script to use ctr for all docker operations - Update userdata sent to the k8s nodes - update cksnode script, run during patching of the cks/k8s nodes --- .../resource/LibvirtComputingResource.java | 26 ++++------------- .../resources/conf/k8s-control-node-add.yml | 10 +++---- .../main/resources/conf/k8s-control-node.yml | 12 ++++---- .../src/main/resources/conf/k8s-node.yml | 10 +++---- .../resources/script/upgrade-kubernetes.sh | 2 +- .../util/create-kubernetes-binaries-iso.sh | 22 +++++++------- .../consoleproxy/ConsoleProxyManagerImpl.java | 8 +++++ .../debian/opt/cloud/bin/setup/cksnode.sh | 9 ++++-- .../opt/cloud/bin/setup/cloud-early-config | 29 +++++++++++++------ systemvm/debian/opt/cloud/bin/setup/common.sh | 6 ++++ systemvm/patch-sysvms.sh | 3 +- .../scripts/configure_systemvm_services.sh | 4 --- .../scripts/install_systemvm_packages.sh | 2 +- 13 files changed, 77 insertions(+), 66 deletions(-) diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index e7cdfbb925f7..99296e2e40fd 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -1168,20 +1168,6 @@ public boolean configure(final String name, final Map params) th _storagePoolMgr = new KVMStoragePoolManager(_storage, _monitor); - _sysvmISOPath = (String)params.get("systemvm.iso.path"); - if (_sysvmISOPath == null) { - final String[] isoPaths = {"/usr/share/cloudstack-common/vms/systemvm.iso"}; - for (final String isoPath : isoPaths) { - if (_storage.exists(isoPath)) { - _sysvmISOPath = isoPath; - break; - } - } - if (_sysvmISOPath == null) { - s_logger.debug("Can't find system vm ISO"); - } - } - final Map bridges = new HashMap(); params.put("libvirt.host.bridges", bridges); @@ -2902,14 +2888,12 @@ public int compare(final DiskTO arg0, final DiskTO arg1) { } if (vmSpec.getType() != VirtualMachine.Type.User) { - if (_sysvmISOPath != null) { - final DiskDef iso = new DiskDef(); - // iso.defISODisk(_sysvmISOPath); - if (_guestCpuArch != null && _guestCpuArch.equals("aarch64")) { - iso.setBusType(DiskDef.DiskBus.SCSI); - } - vm.getDevices().addDevice(iso); + final DiskDef iso = new DiskDef(); + iso.defISODisk(_sysvmISOPath); + if (_guestCpuArch != null && _guestCpuArch.equals("aarch64")) { + iso.setBusType(DiskDef.DiskBus.SCSI); } + vm.getDevices().addDevice(iso); } // For LXC, find and add the root filesystem, rbd data disks diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml index 0891d2015b30..87c592426a96 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml @@ -118,7 +118,7 @@ write_files: fi retval=0 set +e - docker load < "${BINARIES_DIR}/docker/$line" + ctr image import "${BINARIES_DIR}/docker/$line" retval=$? set -e if [ $retval -eq 0 ]; then @@ -165,7 +165,7 @@ write_files: fi systemctl enable kubelet && systemctl start kubelet - modprobe br_netfilter && sysctl net.bridge.bridge-nf-call-iptables=1 + modprobe overlay && modprobe br_netfilter && sysctl net.bridge.bridge-nf-call-iptables=1 if [ -d "$BINARIES_DIR" ] && [ "$ATTEMPT_ONLINE_INSTALL" = true ]; then crucial_cmd_attempts=1 @@ -176,7 +176,7 @@ write_files: fi retval=0 set +e - kubeadm config images pull + kubeadm config images pull --cri-socket /run/containerd/containerd.sock retval=$? set -e if [ $retval -eq 0 ]; then @@ -218,8 +218,8 @@ write_files: owner: root:root content: | [Unit] - Requires=docker.service - After=docker.service + Requires=containerd.service + After=containerd.service [Service] Type=simple diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml index 322f08099cf7..55daf7f6b7d3 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml @@ -138,7 +138,7 @@ write_files: fi retval=0 set +e - docker load < "${BINARIES_DIR}/docker/$line" + ctr image import "${BINARIES_DIR}/docker/$line" retval=$? set -e if [ $retval -eq 0 ]; then @@ -187,7 +187,7 @@ write_files: fi systemctl enable kubelet && systemctl start kubelet - modprobe br_netfilter && sysctl net.bridge.bridge-nf-call-iptables=1 + modprobe overlay && modprobe br_netfilter && sysctl net.bridge.bridge-nf-call-iptables=1 if [ -d "$BINARIES_DIR" ] && [ "$ATTEMPT_ONLINE_INSTALL" = true ]; then crucial_cmd_attempts=1 @@ -198,7 +198,7 @@ write_files: fi retval=0 set +e - kubeadm config images pull + kubeadm config images pull --cri-socket /run/containerd/containerd.sock retval=$? set -e if [ $retval -eq 0 ]; then @@ -216,7 +216,7 @@ write_files: fi retval=0 set +e - kubeadm init --token {{ k8s_control_node.cluster.token }} --token-ttl 0 {{ k8s_control_node.cluster.initargs }} + kubeadm init --token {{ k8s_control_node.cluster.token }} --token-ttl 0 {{ k8s_control_node.cluster.initargs }} --cri-socket /run/containerd/containerd.sock retval=$? set -e if [ $retval -eq 0 ]; then @@ -275,8 +275,8 @@ write_files: owner: root:root content: | [Unit] - Requires=docker.service - After=docker.service + Requires=containerd.service + After=containerd.service [Service] Type=simple diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml index 28ba43e75845..ac05c6098f1a 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml @@ -118,7 +118,7 @@ write_files: fi retval=0 set +e - docker load < "${BINARIES_DIR}/docker/$line" + ctr image import "${BINARIES_DIR}/docker/$line" retval=$? set -e if [ $retval -eq 0 ]; then @@ -165,7 +165,7 @@ write_files: fi systemctl enable kubelet && systemctl start kubelet - modprobe br_netfilter && sysctl net.bridge.bridge-nf-call-iptables=1 + modprobe overlay && modprobe br_netfilter && sysctl net.bridge.bridge-nf-call-iptables=1 if [ -d "$BINARIES_DIR" ] && [ "$ATTEMPT_ONLINE_INSTALL" = true ]; then crucial_cmd_attempts=1 @@ -176,7 +176,7 @@ write_files: fi retval=0 set +e - kubeadm config images pull + kubeadm config images pull --cri-socket /run/containerd/containerd.sock retval=$? set -e if [ $retval -eq 0 ]; then @@ -218,8 +218,8 @@ write_files: owner: root:root content: | [Unit] - Requires=docker.service - After=docker.service + Requires=containerd.service + After=containerd.service [Service] Type=simple diff --git a/plugins/integrations/kubernetes-service/src/main/resources/script/upgrade-kubernetes.sh b/plugins/integrations/kubernetes-service/src/main/resources/script/upgrade-kubernetes.sh index 7e0c3c00a8a5..b85ea00e9ed6 100755 --- a/plugins/integrations/kubernetes-service/src/main/resources/script/upgrade-kubernetes.sh +++ b/plugins/integrations/kubernetes-service/src/main/resources/script/upgrade-kubernetes.sh @@ -93,7 +93,7 @@ if [ -d "$BINARIES_DIR" ]; then output=`ls ${BINARIES_DIR}/docker/` if [ "$output" != "" ]; then while read -r line; do - docker load < "${BINARIES_DIR}/docker/$line" + ctr image import "${BINARIES_DIR}/docker/$line" done <<< "$output" fi if [ -e "${BINARIES_DIR}/provider.yaml" ]; then diff --git a/scripts/util/create-kubernetes-binaries-iso.sh b/scripts/util/create-kubernetes-binaries-iso.sh index ba3dca77a8d2..ce7626c98c22 100755 --- a/scripts/util/create-kubernetes-binaries-iso.sh +++ b/scripts/util/create-kubernetes-binaries-iso.sh @@ -98,19 +98,18 @@ provider_conf_file="${working_dir}/provider.yaml" curl -sSL ${PROVIDER_URL} -o ${provider_conf_file} echo "Fetching k8s docker images..." -docker -v +ctr -v if [ $? -ne 0 ]; then - echo "Installing docker..." + echo "Installing containerd..." if [ -f /etc/redhat-release ]; then sudo yum -y remove docker-common docker container-selinux docker-selinux docker-engine sudo yum -y install lvm2 device-mapper device-mapper-persistent-data device-mapper-event device-mapper-libs device-mapper-event-libs sudo yum install -y http://mirror.centos.org/centos/7/extras/x86_64/Packages/container-selinux-2.107-3.el7.noarch.rpm - sudo wget https://download.docker.com/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo && sudo yum -y install docker-ce - sudo systemctl enable docker && sudo systemctl start docker + sudo yum install -y containerd.io elif [ -f /etc/lsb-release ]; then - sudo apt update && sudo apt install docker.io -y - sudo systemctl enable docker && sudo systemctl start docker + sudo apt update && sudo apt install containerd.io -y fi + sudo systemctl enable containerd && sudo systemctl start containerd fi mkdir -p "${working_dir}/docker" output=`${k8s_dir}/kubeadm config images list --kubernetes-version=${RELEASE}` @@ -130,11 +129,14 @@ provider_image=`grep "image:" ${provider_conf_file} | cut -d ':' -f2- | tr -d ' output=`printf "%s\n" ${output} ${provider_image}` while read -r line; do - echo "Downloading docker image $line ---" - sudo docker pull "$line" + echo "Downloading image $line ---" + if [[ $line == kubernetesui* ]] || [[ $line == apache* ]]; then + line="docker.io/${line}" + fi + sudo ctr image pull "$line" image_name=`echo "$line" | grep -oE "[^/]+$"` - sudo docker save "$line" > "${working_dir}/docker/$image_name.tar" - sudo docker image rm "$line" + sudo ctr image export "${working_dir}/docker/$image_name.tar" "$line" + sudo ctr image rm "$line" done <<< "$output" echo "Restore kubeadm permissions..." diff --git a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index a3177fa77054..7434ea89669c 100644 --- a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -29,7 +29,9 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.utils.PasswordGenerator; import org.apache.cloudstack.agent.lb.IndirectAgentLB; +import org.apache.cloudstack.ca.CAManager; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.framework.config.ConfigKey; @@ -221,6 +223,10 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy private VirtualMachineManager virtualMachineManager; @Inject private IndirectAgentLB indirectAgentLB; + @Inject + private CAManager caManager; + @Inject + private NetworkOrchestrationService networkMgr; private ConsoleProxyListener consoleProxyListener; @@ -1274,6 +1280,8 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl buf.append(" dns2=").append(dc.getDns2()); } + buf.append(" keystore_password=").append(PasswordGenerator.generateRandomPassword(16)); + buf.append(" validity=").append(CAManager.CertValidityPeriod.value()); String bootArgs = buf.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug("Boot Args for " + profile + ": " + bootArgs); diff --git a/systemvm/debian/opt/cloud/bin/setup/cksnode.sh b/systemvm/debian/opt/cloud/bin/setup/cksnode.sh index 612fdd477e8f..7f580ace9cd4 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cksnode.sh +++ b/systemvm/debian/opt/cloud/bin/setup/cksnode.sh @@ -28,18 +28,23 @@ setup_k8s_node() { # set default ssh port and restart sshd service sed -i 's/3922/22/g' /etc/ssh/sshd_config + systemctl restart ssh # Prevent root login > /root/.ssh/authorized_keys passwd -l root #sed -i 's#root:x:0:0:root:/root:/bin/bash#root:x:0:0:root:/root:/sbin/nologin#' /etc/passwd + # Update containerd configuration + mkdir -p /etc/containerd + containerd config default>/etc/containerd/config.toml + systemctl restart containerd + swapoff -a sudo sed -i '/ swap / s/^/#/' /etc/fstab log_it "Swap disabled" log_it "Setting up interfaces" -# setup_common eth0 setup_system_rfc1918_internal log_it "Setting up entry in hosts" @@ -61,8 +66,6 @@ setup_k8s_node() { log_it "Starting cloud-init services" systemctl enable --now --no-block containerd - systemctl enable --now --no-block docker.socket - systemctl enable --now --no-block docker.service if [ -f /home/core/success ]; then systemctl stop cloud-init cloud-config cloud-final systemctl disable cloud-init cloud-config cloud-final diff --git a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config index 9695b18307bb..370dfc0c6205 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config +++ b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config @@ -31,29 +31,40 @@ log_it() { log_action_msg "$@" } +validate_checksums() { + local oldmd5= + [ -f ${1} ] && oldmd5=$(cat ${1}) + local newmd5= + [ -f ${2} ] && newmd5=$(md5sum ${2} | awk '{print $1}') + log_it "Scripts checksum detected: oldmd5=$oldmd5 newmd5=$newmd5" >> /dev/null 2>&1 + echo "oldmd5='${oldmd5}'; newmd5='${newmd5}'" +} + patch() { local PATCH_MOUNT=/home/cloud - local patchfile=$PATCH_MOUNT/cloud-scripts.tgz + local PATCH_SCRIPTS=cloud-scripts.tgz + local oldpatchfile=/usr/share/cloud/$PATCH_SCRIPTS + local patchfile=$PATCH_MOUNT/$PATCH_SCRIPTS local privkey=$PATCH_MOUNT/authorized_keys local md5file=/var/cache/cloud/cloud-scripts-signature - local cdrom_dev= mkdir -p $PATCH_MOUNT if [ -f /var/cache/cloud/authorized_keys ]; then privkey=/var/cache/cloud/authorized_keys fi + eval $(validate_checksums $md5file $oldpatchfile) + if [ "$oldmd5" == "$newmd5" ] && [ ! -f ${patchfile} ]; then + log_it "Checksum matches, do need to patch" + return 0 + fi + retry=60 local patched=false while [ $retry -gt 0 ] do if [ -f $patchfile ]; then - local oldmd5= - [ -f ${md5file} ] && oldmd5=$(cat ${md5file}) - local newmd5= - [ -f ${patchfile} ] && newmd5=$(md5sum ${patchfile} | awk '{print $1}') - log_it "Scripts checksum detected: oldmd5=$oldmd5 newmd5=$newmd5" - log_it ls -lrt $PATCH_MOUNT + eval $(validate_checksums $md5file $patchfile) if [ "$oldmd5" != "$newmd5" ] && [ -f ${patchfile} ] && [ "$newmd5" != "" ] then tar xzf $patchfile -C / @@ -84,7 +95,7 @@ patch() { cleanup() { rm -rf /home/cloud/agent.zip - rm -rf /home/cloud/cloud-scripts.tgz + mv /home/cloud/cloud-scripts.tgz /usr/share/cloud/cloud-scripts.tgz } start() { diff --git a/systemvm/debian/opt/cloud/bin/setup/common.sh b/systemvm/debian/opt/cloud/bin/setup/common.sh index 7f3d85717791..75c8f3cee755 100755 --- a/systemvm/debian/opt/cloud/bin/setup/common.sh +++ b/systemvm/debian/opt/cloud/bin/setup/common.sh @@ -762,6 +762,12 @@ parse_cmd_line() { authorized_key) export AUTHORIZED_KEYS=$VALUE ;; + keystore_password) + export KEYSTORE_PSSWD=$VALUE + ;; + validity) + export VALIDITY=$VALUE + ;; esac done echo -e "\n\t}\n}" >> ${CHEF_TMP_FILE} diff --git a/systemvm/patch-sysvms.sh b/systemvm/patch-sysvms.sh index cf0b452f82ed..31478d7269ae 100644 --- a/systemvm/patch-sysvms.sh +++ b/systemvm/patch-sysvms.sh @@ -76,7 +76,8 @@ restart_services() { cleanup_systemVM() { rm -rf $backupfolder - rm -rf "$newpath""cloud-scripts.tgz" "$newpath""agent.zip" "$newpath""patch-sysvms.sh" + mv "$newpath"cloud-scripts.tgz /usr/share/cloud/cloud-scripts.tgz + rm -rf "$newpath""agent.zip" "$newpath""patch-sysvms.sh" } patch_systemvm() { diff --git a/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh b/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh index 8cdfce787534..4f97b1b5505e 100644 --- a/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh +++ b/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh @@ -127,10 +127,6 @@ function configure_services() { # Disable container services systemctl disable containerd - systemctl disable docker.service - systemctl stop docker.service - systemctl disable docker.socket - systemctl stop docker.socket # Disable cloud init by default cat < /etc/cloud/cloud.cfg.d/cloudstack.cfg diff --git a/tools/appliance/systemvmtemplate/scripts/install_systemvm_packages.sh b/tools/appliance/systemvmtemplate/scripts/install_systemvm_packages.sh index 555a00c28edb..3b4ef6537286 100644 --- a/tools/appliance/systemvmtemplate/scripts/install_systemvm_packages.sh +++ b/tools/appliance/systemvmtemplate/scripts/install_systemvm_packages.sh @@ -98,7 +98,7 @@ function install_packages() { apt-key fingerprint 0EBFCD88 add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" apt-get update - ${apt_get} install docker-ce docker-ce-cli containerd.io + ${apt_get} install containerd.io apt_clean From abc5732f1dd0122150151774c1070c5087923f13 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Tue, 21 Dec 2021 14:55:25 +0530 Subject: [PATCH 30/68] Add ssh to k8s nodes details in the Access tab on the UI --- ui/public/locales/en.json | 2 ++ ui/src/views/compute/KubernetesServiceTab.vue | 3 +++ 2 files changed, 5 insertions(+) diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index bd4bdf80f9e3..d81dd7a1e3ec 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -46,6 +46,7 @@ "label.accept": "Accept", "label.accept.project.invitation": "Accept project invitation", "label.access": "Access", +"label.acess.kubernetes.nodes": "Access Kubernetes Nodes", "label.accesskey": "Access Key", "label.account": "Account", "label.account.and.security.group": "Account - Security group", @@ -1240,6 +1241,7 @@ "label.keypair": "SSH Key Pair", "label.kubeconfig.cluster": "Kubernetes Cluster Config", "label.kubernetes": "Kubernetes", +"label.kubernetes.access.details": "The kubernetes nodes can be accessed via ssh using:
ssh -i [ssh_key] -p [port_number] core@[public_ip_address]

where,
ssh_key: points to the ssh private key file corresponding to the key that was associated while creating the Kubernetes cluster. If no ssh key was provided during Kubernetes cluster creation, use the ssh private key of the management server.
port_number: can be obtained from the Port Forwarding Tab (Public Port column)", "label.kubernetes.cluster": "Kubernetes cluster", "label.kubernetes.cluster.create": "Create Kubernetes Cluster", "label.kubernetes.cluster.delete": "Delete Kubernetes Cluster", diff --git a/ui/src/views/compute/KubernetesServiceTab.vue b/ui/src/views/compute/KubernetesServiceTab.vue index 4cf5486d33f6..9357a2473c5c 100644 --- a/ui/src/views/compute/KubernetesServiceTab.vue +++ b/ui/src/views/compute/KubernetesServiceTab.vue @@ -88,6 +88,9 @@

{{ $t('label.more.access.dashboard.ui') }}, https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/#accessing-the-dashboard-ui

+ +

+
Date: Wed, 22 Dec 2021 14:14:36 +0530 Subject: [PATCH 31/68] test --- .../com/cloud/vm/VirtualMachineManagerImpl.java | 3 +++ engine/schema/pom.xml | 14 ++++++++++---- pom.xml | 2 +- .../consoleproxy/ConsoleProxyManagerImpl.java | 12 +++++++++++- .../debian/opt/cloud/bin/setup/cloud-early-config | 2 +- tools/appliance/build.sh | 6 +++--- 6 files changed, 29 insertions(+), 10 deletions(-) diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index 43f296424662..ff784e7ec801 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -992,6 +992,9 @@ private void setupAgentSecurity(final Host vmHost, final Map ssh final String csr = caManager.generateKeyStoreAndCsr(vmHost, sshAccessDetails); if (org.apache.commons.lang3.StringUtils.isNotEmpty(csr)) { final Map ipAddressDetails = new HashMap<>(sshAccessDetails); + for (Map.Entry e : ipAddressDetails.entrySet()) { + s_logger.info("PEARL - k = " + e.getKey() + " v: "+ e.getValue()); + } ipAddressDetails.remove(NetworkElementCommand.ROUTER_NAME); final Certificate certificate = caManager.issueCertificate(csr, Arrays.asList(vm.getHostName(), vm.getInstanceName()), new ArrayList<>(ipAddressDetails.values()), CAManager.CertValidityPeriod.value(), null); diff --git a/engine/schema/pom.xml b/engine/schema/pom.xml index adee9110007b..165887e19aea 100644 --- a/engine/schema/pom.xml +++ b/engine/schema/pom.xml @@ -90,7 +90,9 @@ def csVersion = pom.properties['cs.version'] + println(csVersion) def patch = pom.properties['patch.version'] + println(patch) def templateList = [] templateList.add("systemvmtemplate-${csVersion}.${patch}-kvm") templateList.add("systemvmtemplate-${csVersion}.${patch}-vmware") @@ -123,7 +125,8 @@ wget - https://download.cloudstack.org/systemvm/${cs.version}/md5sum.txt + + http://10.0.3.122/systemvmtemplate/custom/cks-debian/${cs.version}/md5sum.txt ${basedir}/dist/systemvm-templates/ true true @@ -182,7 +185,8 @@ true - https://download.cloudstack.org/systemvm/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-kvm.qcow2.bz2 + + http://10.0.3.122/systemvmtemplate/custom/cks-debian/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-kvm.qcow2.bz2 ${basedir}/dist/systemvm-templates/ ${kvm.checksum} @@ -194,7 +198,8 @@ true - https://download.cloudstack.org/systemvm/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-vmware.ova + + http://10.0.3.122/systemvmtemplate/custom/cks-debian/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-vmware.ova ${basedir}/dist/systemvm-templates/ ${vmware.checksum} @@ -206,7 +211,8 @@ true - https://download.cloudstack.org/systemvm/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-xen.vhd.bz2 + + http://10.0.3.122/systemvmtemplate/custom/cks-debian/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-xen.vhd.bz2 ${basedir}/dist/systemvm-templates/ ${xen.checksum} diff --git a/pom.xml b/pom.xml index 718430eb867e..4daaa8ccfca5 100644 --- a/pom.xml +++ b/pom.xml @@ -49,7 +49,7 @@ UTF-8 UTF-8 - 4.16.0.0 + 4.16.1.0 11 diff --git a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 7434ea89669c..1dcaf7b0b33e 100644 --- a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -1210,7 +1210,8 @@ protected ConsoleProxyManagerImpl() { @Override public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { - +// final Certificate certificate = caManager.issueCertificate(null, Arrays.asList(profile.getHostName(), profile.getInstanceName()), +// new ArrayList<>(ipAddressDetails.values()), CAManager.CertValidityPeriod.value(), null); ConsoleProxyVO vm = consoleProxyDao.findById(profile.getId()); Map details = userVmDetailsDao.listDetailsKeyPairs(vm.getId()); vm.setDetails(details); @@ -1280,6 +1281,15 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl buf.append(" dns2=").append(dc.getDns2()); } +// try { +// buf.append(" certificate=").append(CertUtils.x509CertificateToPem(certificate.getClientCertificate())); +// buf.append(" cacertificate=").append(CertUtils.x509CertificatesToPem(certificate.getCaCertificates())); +// if (certificate.getPrivateKey() != null) { +// buf.append(" privatekey=").append(CertUtils.privateKeyToPem(certificate.getPrivateKey())); +// } +// } catch (IOException e) { +// throw new CloudRuntimeException("Failed to transform X509 cert to PEM format", e); +// } buf.append(" keystore_password=").append(PasswordGenerator.generateRandomPassword(16)); buf.append(" validity=").append(CAManager.CertValidityPeriod.value()); String bootArgs = buf.toString(); diff --git a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config index 370dfc0c6205..5a50fe850079 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config +++ b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config @@ -54,7 +54,7 @@ patch() { fi eval $(validate_checksums $md5file $oldpatchfile) - if [ "$oldmd5" == "$newmd5" ] && [ ! -f ${patchfile} ]; then + if [ "$oldmd5" == "$newmd5" ] && [ -d /usr/local/cloud/systemvm ] && [ "$(ls -A /usr/local/cloud/systemvm)" ]; then log_it "Checksum matches, do need to patch" return 0 fi diff --git a/tools/appliance/build.sh b/tools/appliance/build.sh index 7075c135d42d..285d818c0c75 100755 --- a/tools/appliance/build.sh +++ b/tools/appliance/build.sh @@ -348,9 +348,9 @@ function main() { packer_build # process the disk at dist - kvm_export - ovm_export - xen_server_export +# kvm_export +# ovm_export +# xen_server_export vmware_export # hyperv_export rm -f "dist/${appliance}" From 87f1b73d0feefc3972e4a92881ca93df0bc98671 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Fri, 24 Dec 2021 12:20:41 +0530 Subject: [PATCH 32/68] Refactor ca/cert patching logic --- .../java/com/cloud/vm/VirtualMachineGuru.java | 25 +++++++++++ .../cloud/vm/VirtualMachineManagerImpl.java | 17 ------- scripts/util/keystore-cert-import | 45 ++++++++++++------- .../consoleproxy/ConsoleProxyManagerImpl.java | 21 +++------ .../com/cloud/consoleproxy/ConsoleProxy.java | 10 ++++- .../SecondaryStorageManagerImpl.java | 11 +++++ .../opt/cloud/bin/setup/cloud-early-config | 2 +- systemvm/debian/opt/cloud/bin/setup/common.sh | 22 ++++++++- .../opt/cloud/bin/setup/consoleproxy.sh | 2 + .../debian/opt/cloud/bin/setup/secstorage.sh | 1 + 10 files changed, 104 insertions(+), 52 deletions(-) diff --git a/engine/api/src/main/java/com/cloud/vm/VirtualMachineGuru.java b/engine/api/src/main/java/com/cloud/vm/VirtualMachineGuru.java index 7611df820c80..d6d7513fd5c6 100644 --- a/engine/api/src/main/java/com/cloud/vm/VirtualMachineGuru.java +++ b/engine/api/src/main/java/com/cloud/vm/VirtualMachineGuru.java @@ -20,7 +20,14 @@ import com.cloud.agent.manager.Commands; import com.cloud.deploy.DeployDestination; import com.cloud.exception.ResourceUnavailableException; +import com.cloud.utils.PasswordGenerator; +import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.cloudstack.ca.CAManager; +import org.apache.cloudstack.framework.ca.Certificate; +import org.apache.cloudstack.utils.security.CertUtils; +import org.apache.cloudstack.utils.security.KeyStoreUtils; +import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Base64; @@ -72,4 +79,22 @@ static String getEncodedMsPublicKey(String pubKey) { } return base64EncodedPublicKey; } + + private static String getEncodedString(String certificate) { + return Base64.getEncoder().encodeToString(certificate.replace("\n", KeyStoreUtils.CERT_NEWLINE_ENCODER).replace(" ", KeyStoreUtils.CERT_SPACE_ENCODER).getBytes(StandardCharsets.UTF_8)); + } + + static void appendCertificateDetails(StringBuilder buf, Certificate certificate) { + try { + buf.append(" certificate=").append(getEncodedString(CertUtils.x509CertificateToPem(certificate.getClientCertificate()))); + buf.append(" cacertificate=").append(getEncodedString(CertUtils.x509CertificatesToPem(certificate.getCaCertificates()))); + if (certificate.getPrivateKey() != null) { + buf.append(" privatekey=").append(getEncodedString(CertUtils.privateKeyToPem(certificate.getPrivateKey()))); + } + } catch (IOException e) { + throw new CloudRuntimeException("Failed to transform X509 cert to PEM format", e); + } + buf.append(" keystore_password=").append(getEncodedString(PasswordGenerator.generateRandomPassword(16))); + buf.append(" validity=").append(CAManager.CertValidityPeriod.value()); + } } diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index ff784e7ec801..26b6bc38e173 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -992,9 +992,6 @@ private void setupAgentSecurity(final Host vmHost, final Map ssh final String csr = caManager.generateKeyStoreAndCsr(vmHost, sshAccessDetails); if (org.apache.commons.lang3.StringUtils.isNotEmpty(csr)) { final Map ipAddressDetails = new HashMap<>(sshAccessDetails); - for (Map.Entry e : ipAddressDetails.entrySet()) { - s_logger.info("PEARL - k = " + e.getKey() + " v: "+ e.getValue()); - } ipAddressDetails.remove(NetworkElementCommand.ROUTER_NAME); final Certificate certificate = caManager.issueCertificate(csr, Arrays.asList(vm.getHostName(), vm.getInstanceName()), new ArrayList<>(ipAddressDetails.values()), CAManager.CertValidityPeriod.value(), null); @@ -1246,20 +1243,6 @@ public void orchestrateStart(final String vmUuid, final Map sshAccessDetails = _networkMgr.getSystemVMAccessDetails(vm); - for (int retries = 3; retries > 0; retries--) { - try { - setupAgentSecurity(vmHost, sshAccessDetails, vm); - return; - } catch (final AgentUnavailableException | OperationTimedoutException e) { - s_logger.error("Retrying after catching exception while trying to secure agent for systemvm id=" + vm.getId(), e); - } - } - throw new CloudRuntimeException("Failed to setup and secure agent for systemvm id=" + vm.getId()); - } return; } else { if (s_logger.isDebugEnabled()) { diff --git a/scripts/util/keystore-cert-import b/scripts/util/keystore-cert-import index a2b57bff07e2..8e63e9509cc0 100755 --- a/scripts/util/keystore-cert-import +++ b/scripts/util/keystore-cert-import @@ -17,19 +17,39 @@ # under the License. PROPS_FILE="$1" -KS_FILE="$2" -MODE="$3" -CERT_FILE="$4" -CERT=$(echo "$5" | tr '^' '\n' | tr '~' ' ') -CACERT_FILE="$6" -CACERT=$(echo "$7" | tr '^' '\n' | tr '~' ' ') -PRIVKEY_FILE="$8" -PRIVKEY=$(echo "$9" | tr '^' '\n' | tr '~' ' ') +KS_PASS="$2" +KS_VALIDITY="$3" +KS_FILE="$4" +MODE="$5" +CERT_FILE="$6" +CERT=$(echo "$7" | tr '^' '\n' | tr '~' ' ') +CACERT_FILE="$8" +CACERT=$(echo "$9" | tr '^' '\n' | tr '~' ' ') +PRIVKEY_FILE="${10}" +PRIVKEY=$(echo "${11}" | tr '^' '\n' | tr '~' ' ') ALIAS="cloud" SYSTEM_FILE="/var/cache/cloud/cmdline" LIBVIRTD_FILE="/etc/libvirt/libvirtd.conf" +# Re-use existing password or use the one provided +if [ -f "$PROPS_FILE" ]; then + OLD_PASS=$(sed -n '/keystore.passphrase/p' "$PROPS_FILE" 2>/dev/null | sed 's/keystore.passphrase=//g' 2>/dev/null) + if [ ! -z "${OLD_PASS// }" ]; then + KS_PASS="$OLD_PASS" + else + sed -i "/keystore.passphrase.*/d" $PROPS_FILE 2> /dev/null || true + echo "keystore.passphrase=$KS_PASS" >> $PROPS_FILE + fi +fi + +if [ -f "$KS_FILE" ]; then + keytool -delete -noprompt -alias "$ALIAS" -keystore "$KS_FILE" -storepass "$KS_PASS" > /dev/null 2>&1 || true +fi + +CN=$(hostname --fqdn) +keytool -genkey -storepass "$KS_PASS" -keypass "$KS_PASS" -alias "$ALIAS" -keyalg RSA -validity "$KS_VALIDITY" -dname cn="$CN",ou="cloudstack",o="cloudstack",c="cloudstack" -keystore "$KS_FILE" > /dev/null 2>&1 + # Find keystore password KS_PASS=$(sed -n '/keystore.passphrase/p' "$PROPS_FILE" 2>/dev/null | sed 's/keystore.passphrase=//g' 2>/dev/null) @@ -56,11 +76,6 @@ for caChain in $(ls cloudca.*); do done rm -f cloudca.* -# Stop cloud service in systemvm -if [ "$MODE" == "ssh" ] && [ -f $SYSTEM_FILE ]; then - systemctl stop cloud > /dev/null 2>&1 -fi - # Import private key if available if [ ! -z "${PRIVKEY// }" ]; then echo "$PRIVKEY" > "$PRIVKEY_FILE" @@ -99,10 +114,6 @@ if [ -f "$SYSTEM_FILE" ]; then chmod 644 /usr/local/share/ca-certificates/cloudstack/ca.crt update-ca-certificates > /dev/null 2>&1 || true - # Ensure cloud service is running in systemvm - if [ "$MODE" == "ssh" ]; then - systemctl start cloud > /dev/null 2>&1 - fi fi # Fix file permission diff --git a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 1dcaf7b0b33e..40c6363ce169 100644 --- a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -29,11 +29,11 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.utils.PasswordGenerator; import org.apache.cloudstack.agent.lb.IndirectAgentLB; import org.apache.cloudstack.ca.CAManager; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; +import org.apache.cloudstack.framework.ca.Certificate; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; @@ -1210,8 +1210,11 @@ protected ConsoleProxyManagerImpl() { @Override public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { -// final Certificate certificate = caManager.issueCertificate(null, Arrays.asList(profile.getHostName(), profile.getInstanceName()), -// new ArrayList<>(ipAddressDetails.values()), CAManager.CertValidityPeriod.value(), null); + final Map sshAccessDetails = networkMgr.getSystemVMAccessDetails(profile.getVirtualMachine()); + final Map ipAddressDetails = new HashMap<>(sshAccessDetails); + ipAddressDetails.remove("router.name"); + final Certificate certificate = caManager.issueCertificate(null, Arrays.asList(profile.getHostName(), profile.getInstanceName()), + new ArrayList<>(ipAddressDetails.values()), CAManager.CertValidityPeriod.value(), null); ConsoleProxyVO vm = consoleProxyDao.findById(profile.getId()); Map details = userVmDetailsDao.listDetailsKeyPairs(vm.getId()); vm.setDetails(details); @@ -1281,17 +1284,7 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl buf.append(" dns2=").append(dc.getDns2()); } -// try { -// buf.append(" certificate=").append(CertUtils.x509CertificateToPem(certificate.getClientCertificate())); -// buf.append(" cacertificate=").append(CertUtils.x509CertificatesToPem(certificate.getCaCertificates())); -// if (certificate.getPrivateKey() != null) { -// buf.append(" privatekey=").append(CertUtils.privateKeyToPem(certificate.getPrivateKey())); -// } -// } catch (IOException e) { -// throw new CloudRuntimeException("Failed to transform X509 cert to PEM format", e); -// } - buf.append(" keystore_password=").append(PasswordGenerator.generateRandomPassword(16)); - buf.append(" validity=").append(CAManager.CertValidityPeriod.value()); + VirtualMachineGuru.appendCertificateDetails(buf, certificate); String bootArgs = buf.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug("Boot Args for " + profile + ": " + bootArgs); diff --git a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java index fd4f68bcee04..8f6f12b07649 100644 --- a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java +++ b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java @@ -32,6 +32,7 @@ import java.util.concurrent.Executor; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.ArrayUtils; import org.apache.log4j.xml.DOMConfigurator; import org.eclipse.jetty.websocket.api.Session; @@ -74,6 +75,7 @@ public class ConsoleProxy { static boolean standaloneStart = false; static String encryptorPassword = "Dummy"; + static final String[] skipProperties = new String[]{"certificate", "cacertificate", "keystore_password", "privatekey"}; private static void configLog4j() { final ClassLoader loader = Thread.currentThread().getContextClassLoader(); @@ -108,7 +110,9 @@ private static void configLog4j() { private static void configProxy(Properties conf) { s_logger.info("Configure console proxy..."); for (Object key : conf.keySet()) { - s_logger.info("Property " + (String)key + ": " + conf.getProperty((String)key)); + if (!ArrayUtils.contains(skipProperties, key)) { + s_logger.info("Property " + (String)key + ": " + conf.getProperty((String)key)); + } } String s = conf.getProperty("consoleproxy.httpListenPort"); @@ -247,7 +251,9 @@ public static void startWithContext(Properties conf, Object context, byte[] ksBi if (conf != null) { for (Object key : conf.keySet()) { - s_logger.info("Context property " + (String)key + ": " + conf.getProperty((String)key)); + if (!ArrayUtils.contains(skipProperties, key)) { + s_logger.info("Context property " + (String) key + ": " + conf.getProperty((String) key)); + } } } diff --git a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java index d3d64fe10f5f..fb300cbbeb93 100644 --- a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java +++ b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java @@ -31,11 +31,13 @@ import javax.naming.ConfigurationException; import org.apache.cloudstack.agent.lb.IndirectAgentLB; +import org.apache.cloudstack.ca.CAManager; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; +import org.apache.cloudstack.framework.ca.Certificate; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; @@ -245,6 +247,8 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar private ImageStoreDetailsUtil imageStoreDetailsUtil; @Inject private IndirectAgentLB indirectAgentLB; + @Inject + private CAManager caManager; private long _capacityScanInterval = DEFAULT_CAPACITY_SCAN_INTERVAL_IN_MILLISECONDS; private int _secStorageVmMtuSize; @@ -1070,6 +1074,12 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl return false; } + final Map sshAccessDetails = _networkMgr.getSystemVMAccessDetails(profile.getVirtualMachine()); + final Map ipAddressDetails = new HashMap<>(sshAccessDetails); + ipAddressDetails.remove("router.name"); + final Certificate certificate = caManager.issueCertificate(null, Arrays.asList(profile.getHostName(), profile.getInstanceName()), + new ArrayList<>(ipAddressDetails.values()), CAManager.CertValidityPeriod.value(), null); + StringBuilder buf = profile.getBootArgsBuilder(); buf.append(" template=domP type=secstorage"); buf.append(" host=").append(com.cloud.utils.StringUtils.toCSVList(indirectAgentLB.getManagementServerList(dest.getHost().getId(), dest.getDataCenter().getId(), null))); @@ -1155,6 +1165,7 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl String nfsVersion = imageStoreDetailsUtil != null ? imageStoreDetailsUtil.getNfsVersion(secStore.getId()) : null; buf.append(" nfsVersion=").append(nfsVersion); + VirtualMachineGuru.appendCertificateDetails(buf, certificate); String bootArgs = buf.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug(String.format("Boot args for machine profile [%s]: [%s].", profile.toString(), bootArgs)); diff --git a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config index 5a50fe850079..15da63e93c6b 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config +++ b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config @@ -55,7 +55,7 @@ patch() { eval $(validate_checksums $md5file $oldpatchfile) if [ "$oldmd5" == "$newmd5" ] && [ -d /usr/local/cloud/systemvm ] && [ "$(ls -A /usr/local/cloud/systemvm)" ]; then - log_it "Checksum matches, do need to patch" + log_it "Checksum matches, no need to patch" return 0 fi diff --git a/systemvm/debian/opt/cloud/bin/setup/common.sh b/systemvm/debian/opt/cloud/bin/setup/common.sh index 75c8f3cee755..be0b1c46b890 100755 --- a/systemvm/debian/opt/cloud/bin/setup/common.sh +++ b/systemvm/debian/opt/cloud/bin/setup/common.sh @@ -593,6 +593,17 @@ routing_svcs() { fi } +setup_certificates() { + certificate=$(echo "$CERTIFICATE" | base64 -d) + cacertificate=$(echo "$CACERTIFICATE" | base64 -d) + privatekey=$(echo "$PRIVATEKEY" | base64 -d) + kspass=$(echo "$KEYSTORE_PSSWD"| base64 -d) + ksvalidity="$KS_VALIDITY" + /opt/cloud/bin/keystore-cert-import /usr/local/cloud/systemvm/conf/agent.properties $kspass $ksvalidity \ + /usr/local/cloud/systemvm/conf/cloud.jks ssh /usr/local/cloud/systemvm/conf/cloud.crt \ + $certificate /usr/local/cloud/systemvm/conf/cloud.ca.crt $cacertificate /usr/local/cloud/systemvm/conf/cloud.key $privatekey +} + parse_cmd_line() { CMDLINE=$(cat /var/cache/cloud/cmdline) TYPE="unknown" @@ -766,7 +777,16 @@ parse_cmd_line() { export KEYSTORE_PSSWD=$VALUE ;; validity) - export VALIDITY=$VALUE + export KS_VALIDITY=$VALUE + ;; + certificate) + export CERTIFICATE=$VALUE + ;; + cacertificate) + export CACERTIFICATE=$VALUE + ;; + privatekey) + export PRIVATEKEY=$VALUE ;; esac done diff --git a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh index ec45b7ffc942..324f92e90859 100755 --- a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh +++ b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh @@ -36,6 +36,8 @@ setup_console_proxy() { enable_fwding 0 enable_irqbalance 0 rm -f /etc/logrotate.d/cloud + + setup_certificates } setup_console_proxy diff --git a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh index 3b21ed5cae17..a34e671ba948 100755 --- a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh +++ b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh @@ -66,6 +66,7 @@ CORS setup_ntp rm -f /etc/logrotate.d/cloud + setup_certificates } setup_secstorage From 10f6d33849af4a03eb927c11b434f50b140085e1 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Wed, 29 Dec 2021 17:33:31 +0530 Subject: [PATCH 33/68] Commit comprises of the following changes: - Use restart network/VPC API to patch routers - use livePatch API support patching of only cpvm/ssvm - add timeout to the keystore setup/import script --- .../main/java/com/cloud/agent/AgentShell.java | 8 +-- .../com/cloud/network/NetworkService.java | 2 +- .../com/cloud/network/vpc/VpcService.java | 2 +- .../apache/cloudstack/api/ApiConstants.java | 1 + .../user/network/RestartNetworkCmd.java | 5 ++ .../api/command/user/vpc/RestartVPCCmd.java | 5 ++ .../service/NetworkOrchestrationService.java | 2 +- .../orchestration/NetworkOrchestrator.java | 29 ++++++++-- .../com/cloud/vm/dao/ConsoleProxyDaoImpl.java | 2 +- .../LibvirtPatchSystemVmCommandWrapper.java | 2 +- .../vmware/resource/VmwareResource.java | 10 ++-- .../CitrixPatchSystemVmCommandWrapper.java | 1 - .../com/cloud/network/NetworkServiceImpl.java | 15 +++-- .../VirtualNetworkApplianceManagerImpl.java | 4 +- .../com/cloud/network/vpc/VpcManagerImpl.java | 17 ++++-- .../com/cloud/server/ManagementServer.java | 3 + .../cloud/server/ManagementServerImpl.java | 58 ++++++++++++++++--- .../com/cloud/vpc/MockNetworkManagerImpl.java | 4 +- .../opt/cloud/bin/setup/consoleproxy.sh | 5 +- .../debian/opt/cloud/bin/setup/secstorage.sh | 5 +- systemvm/patch-sysvms.sh | 19 +++--- .../java/com/cloud/utils/script/Script.java | 2 +- 22 files changed, 146 insertions(+), 55 deletions(-) diff --git a/agent/src/main/java/com/cloud/agent/AgentShell.java b/agent/src/main/java/com/cloud/agent/AgentShell.java index 7d395dff9591..28e38e4cdddb 100644 --- a/agent/src/main/java/com/cloud/agent/AgentShell.java +++ b/agent/src/main/java/com/cloud/agent/AgentShell.java @@ -423,13 +423,13 @@ private void launchAgentFromClassInfo(String resourceClassNames) throws Configur } catch (final ClassNotFoundException e) { throw new ConfigurationException("Resource class not found: " + name + " due to: " + e.toString()); } catch (final SecurityException e) { - throw new ConfigurationException("Security excetion when loading resource: " + name + " due to: " + e.toString()); + throw new ConfigurationException("Security exception when loading resource: " + name + " due to: " + e.toString()); } catch (final NoSuchMethodException e) { - throw new ConfigurationException("Method not found excetion when loading resource: " + name + " due to: " + e.toString()); + throw new ConfigurationException("Method not found exception when loading resource: " + name + " due to: " + e.toString()); } catch (final IllegalArgumentException e) { - throw new ConfigurationException("Illegal argument excetion when loading resource: " + name + " due to: " + e.toString()); + throw new ConfigurationException("Illegal argument exception when loading resource: " + name + " due to: " + e.toString()); } catch (final InstantiationException e) { - throw new ConfigurationException("Instantiation excetion when loading resource: " + name + " due to: " + e.toString()); + throw new ConfigurationException("Instantiation exception when loading resource: " + name + " due to: " + e.toString()); } catch (final IllegalAccessException e) { throw new ConfigurationException("Illegal access exception when loading resource: " + name + " due to: " + e.toString()); } catch (final InvocationTargetException e) { diff --git a/api/src/main/java/com/cloud/network/NetworkService.java b/api/src/main/java/com/cloud/network/NetworkService.java index 297bcbdc8a8a..f37dd88ffed5 100644 --- a/api/src/main/java/com/cloud/network/NetworkService.java +++ b/api/src/main/java/com/cloud/network/NetworkService.java @@ -72,7 +72,7 @@ IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long ne boolean deleteNetwork(long networkId, boolean forced); - boolean restartNetwork(Long networkId, boolean cleanup, boolean makeRedundant, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; + boolean restartNetwork(Long networkId, boolean cleanup, boolean makeRedundant, boolean livePatch, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; boolean restartNetwork(RestartNetworkCmd cmd) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; diff --git a/api/src/main/java/com/cloud/network/vpc/VpcService.java b/api/src/main/java/com/cloud/network/vpc/VpcService.java index d7c83f91678e..32c697a000da 100644 --- a/api/src/main/java/com/cloud/network/vpc/VpcService.java +++ b/api/src/main/java/com/cloud/network/vpc/VpcService.java @@ -136,7 +136,7 @@ public Pair, Integer> listVpcs(Long id, String vpcName, Stri */ boolean restartVpc(RestartVPCCmd cmd) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; - boolean restartVpc(Long networkId, boolean cleanup, boolean makeRedundant, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; + boolean restartVpc(Long networkId, boolean cleanup, boolean makeRedundant, boolean livePatch, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; /** * Returns a Private gateway found in the VPC by id diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index 94e6a7deeb0f..cd2572467ab2 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -33,6 +33,7 @@ public class ApiConstants { public static final String USER_API_KEY = "userapikey"; public static final String APPLIED = "applied"; public static final String LIST_LB_VMIPS = "lbvmips"; + public static final String LIVE_PATCH = "livepatch"; public static final String AVAILABLE = "available"; public static final String BACKUP_ID = "backupid"; public static final String BACKUP_OFFERING_NAME = "backupofferingname"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java index dbcdb8f88846..445130c4c333 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java @@ -59,6 +59,9 @@ public class RestartNetworkCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.MAKEREDUNDANT, type = CommandType.BOOLEAN, required = false, description = "Turn the network into a network with redundant routers.", since = "4.11.1") private Boolean makeRedundant = false; + @Parameter(name = ApiConstants.LIVE_PATCH, type = CommandType.BOOLEAN, required = false, description = "Live Patch the router before restarting it", since = "4.16.1") + private Boolean livePatch = false; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -80,6 +83,8 @@ public Boolean getMakeRedundant() { return makeRedundant; } + public Boolean getLivePatch() { return livePatch; } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java index aade0c2886a5..0e9689816471 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java @@ -54,6 +54,9 @@ public class RestartVPCCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.MAKEREDUNDANT, type = CommandType.BOOLEAN, required = false, description = "Turn a single VPC into a redundant one.") private Boolean makeredundant = false; + @Parameter(name = ApiConstants.LIVE_PATCH, type = CommandType.BOOLEAN, required = false, description = "Live Patch the router before restarting it", since = "4.16.1") + private Boolean livePatch = false; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -70,6 +73,8 @@ public Boolean getMakeredundant() { return makeredundant; } + public Boolean getLivePatch() { return livePatch; } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java index 1673575780cb..16ddfa6ebead 100644 --- a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java @@ -251,7 +251,7 @@ NicProfile createNicForVm(Network network, NicProfile requested, ReservationCont NetworkProfile convertNetworkToNetworkProfile(long networkId); - boolean restartNetwork(Long networkId, Account callerAccount, User callerUser, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException, + boolean restartNetwork(Long networkId, Account callerAccount, User callerUser, boolean cleanup, boolean livePatch) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; boolean shutdownNetworkElementsAndResources(ReservationContext context, boolean b, Network network); diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index e6a95f41f0c5..72073e92484f 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -38,6 +38,7 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.server.ManagementServer; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.annotation.AnnotationService; import org.apache.cloudstack.annotation.dao.AnnotationDao; @@ -305,7 +306,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra @Inject VMNetworkMapDao _vmNetworkMapDao; @Inject - DomainRouterDao _routerDao; + DomainRouterDao routerDao; @Inject RemoteAccessVpnDao _remoteAccessVpnDao; @Inject @@ -318,6 +319,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra ResourceManager resourceManager; @Inject private AnnotationDao annotationDao; + @Inject + public ManagementServer mgr; List networkGurus; @@ -1622,7 +1625,7 @@ public boolean canUpdateInSequence(Network network, boolean forced){ throw new UnsupportedOperationException("Cannot update the network resources in sequence when providers other than virtualrouter are used"); } //check if routers are in correct state before proceeding with the update - List routers = _routerDao.listByNetworkAndRole(network.getId(), VirtualRouter.Role.VIRTUAL_ROUTER); + List routers = routerDao.listByNetworkAndRole(network.getId(), VirtualRouter.Role.VIRTUAL_ROUTER); for (DomainRouterVO router : routers){ if (router.getRedundantState() == VirtualRouter.RedundantState.UNKNOWN) { if (!forced) { @@ -3273,7 +3276,7 @@ public boolean startNetwork(final long networkId, final DeployDestination dest, } @Override - public boolean restartNetwork(final Long networkId, final Account callerAccount, final User callerUser, final boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException, + public boolean restartNetwork(final Long networkId, final Account callerAccount, final User callerUser, final boolean cleanup, final boolean livePatch) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { boolean status = true; boolean restartRequired = false; @@ -3292,6 +3295,20 @@ public boolean restartNetwork(final Long networkId, final Account callerAccount, } setRestartRequired(network, restartRequired); return status; + } else if (livePatch) { + List domainRouters = routerDao.listByNetworkAndRole(network.getId(), VirtualRouter.Role.VIRTUAL_ROUTER); + for (DomainRouterVO router: domainRouters) { + try { + VMInstanceVO instanceVO = _vmDao.findById(router.getId()); + Pair patched = mgr.updateSystemVM(instanceVO, true); + if (patched.first()) { + s_logger.info(String.format("Successfully patched router %s", router)); + } + } catch (CloudRuntimeException e) { + throw new CloudRuntimeException(String.format("Failed to live patch router: %s", router), e); + } + + } } s_logger.debug("Implementing the network " + network + " elements and resources as a part of network restart without cleanup"); @@ -3401,10 +3418,10 @@ private boolean rollingRestartRouters(final NetworkVO network, final NetworkOffe return false; } s_logger.debug("Performing rolling restart of routers of network " + network); - destroyExpendableRouters(_routerDao.findByNetwork(network.getId()), context); + destroyExpendableRouters(routerDao.findByNetwork(network.getId()), context); final List providersToImplement = getNetworkProviders(network.getId()); - final List oldRouters = _routerDao.findByNetwork(network.getId()); + final List oldRouters = routerDao.findByNetwork(network.getId()); // Deploy a new router if (oldRouters.size() > 0) { @@ -3436,7 +3453,7 @@ private boolean rollingRestartRouters(final NetworkVO network, final NetworkOffe implementNetworkElementsAndResources(dest, context, network, offering); } - return areRoutersRunning(_routerDao.findByNetwork(network.getId())); + return areRoutersRunning(routerDao.findByNetwork(network.getId())); } private void setRestartRequired(final NetworkVO network, final boolean restartRequired) { diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/ConsoleProxyDaoImpl.java b/engine/schema/src/main/java/com/cloud/vm/dao/ConsoleProxyDaoImpl.java index 36ff74b11b37..dcf6505ce221 100644 --- a/engine/schema/src/main/java/com/cloud/vm/dao/ConsoleProxyDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/ConsoleProxyDaoImpl.java @@ -52,7 +52,7 @@ public class ConsoleProxyDaoImpl extends GenericDaoBase im + " AS runningVm ON c.id = runningVm.proxy_id WHERE i.state='Running' " + " GROUP BY c.id"; // - // query SQL for returnning running VM count at data center basis + // query SQL for returning running VM count at data center basis // private static final String DATACENTER_VM_MATRIX = "SELECT d.id, d.name, count(v.id) AS count" + " FROM data_center AS d LEFT JOIN vm_instance AS v ON v.data_center_id=d.id " diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java index 5fac33ebec22..b2d64393c111 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java @@ -72,7 +72,7 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR Pair patchResult = null; try { patchResult = SshHelper.sshExecute(controlIp, sshPort, "root", - pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 60000); + pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 600000); } catch (Exception e) { return new PatchSystemVmAnswer(cmd, e.getMessage()); } diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index f258f6a6f8e5..6dab0721e86c 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -470,7 +470,9 @@ public Answer executeRequest(Command cmd) { mbean.addProp("Name", cmd.getClass().getSimpleName()); Class clz = cmd.getClass(); - if (cmd instanceof NetworkElementCommand) { + if (clz == PatchSystemVmCommand.class) { + answer = execute((PatchSystemVmCommand) cmd); + } else if (cmd instanceof NetworkElementCommand) { return _vrResource.executeRequest((NetworkElementCommand) cmd); } else if (clz == ReadyCommand.class) { answer = execute((ReadyCommand) cmd); @@ -595,9 +597,7 @@ public Answer executeRequest(Command cmd) { answer = execute((SetupPersistentNetworkCommand) cmd); } else if (clz == GetVmVncTicketCommand.class) { answer = execute((GetVmVncTicketCommand) cmd); - } else if (clz == PatchSystemVmCommand.class) { - answer = execute((PatchSystemVmCommand) cmd); - } else { + } else { answer = Answer.createUnsupportedCommandAnswer(cmd); } @@ -687,7 +687,7 @@ private Answer execute(PatchSystemVmCommand cmd) { Pair patchResult = null; try { patchResult = SshHelper.sshExecute(controlIp, DefaultDomRSshPort, "root", - pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 60000); + pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 600000); } catch (Exception e) { return new PatchSystemVmAnswer(cmd, e.getMessage()); } diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java index a6b183f9d11e..883c9378aa0c 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java @@ -48,7 +48,6 @@ public Answer execute(PatchSystemVmCommand command, CitrixResourceBase serverRes try { result = getSystemVmVersionAndChecksum(serverResource, controlIp); serverResource.copyPatchFilesToVR(controlIp, "/home/cloud"); - //FileUtil.scpPatchFiles(controlIp, "/home/cloud", sshPort, pemFile, serverResource.newSrcFiles, CitrixResourceBase.BASEPATH); } catch (CloudRuntimeException e) { return new PatchSystemVmAnswer(command, e.getMessage()); } diff --git a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java index 411438059d78..805295080811 100644 --- a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java @@ -2026,9 +2026,9 @@ public boolean deleteNetwork(long networkId, boolean forced) { @Override @ActionEvent(eventType = EventTypes.EVENT_NETWORK_RESTART, eventDescription = "restarting network", async = true) - public boolean restartNetwork(Long networkId, boolean cleanup, boolean makeRedundant, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { + public boolean restartNetwork(Long networkId, boolean cleanup, boolean makeRedundant, boolean livePatch, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { NetworkVO network = getNetworkVO(networkId, "Network with specified id doesn't exist"); - return restartNetwork(network, cleanup, makeRedundant, user); + return restartNetwork(network, cleanup, makeRedundant, livePatch, user); } private NetworkVO getNetworkVO(Long networkId, String errMsgFormat) { @@ -2040,7 +2040,7 @@ private NetworkVO getNetworkVO(Long networkId, String errMsgFormat) { } @ActionEvent(eventType = EventTypes.EVENT_NETWORK_RESTART, eventDescription = "restarting network", async = true) - public boolean restartNetwork(NetworkVO network, boolean cleanup, boolean makeRedundant, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { + public boolean restartNetwork(NetworkVO network, boolean cleanup, boolean makeRedundant, boolean livePatch, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { // Don't allow to restart network if it's not in Implemented/Setup state if (!(network.getState() == Network.State.Implemented || network.getState() == Network.State.Setup)) { @@ -2065,9 +2065,11 @@ public boolean restartNetwork(NetworkVO network, boolean cleanup, boolean makeRe } cleanup = true; } - + if (cleanup) { + livePatch = false; + } long id = network.getId(); - boolean success = _networkMgr.restartNetwork(id, callerAccount, user, cleanup); + boolean success = _networkMgr.restartNetwork(id, callerAccount, user, cleanup, livePatch); if (success) { s_logger.debug(String.format("Network id=%d is restarted successfully.",id)); } else { @@ -2087,8 +2089,9 @@ public boolean restartNetwork(RestartNetworkCmd cmd) throws ConcurrentOperationE throwInvalidIdException("Cannot restart a VPC tier with cleanup, please restart the whole VPC.", network.getUuid(), "network tier"); } boolean makeRedundant = cmd.getMakeRedundant(); + boolean livePatch = cmd.getLivePatch(); User callerUser = _accountMgr.getActiveUser(CallContext.current().getCallingUserId()); - return restartNetwork(network, cleanup, makeRedundant, callerUser); + return restartNetwork(network, cleanup, makeRedundant, livePatch, callerUser); } @Override diff --git a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 40d5e677e500..90598cfbfdfa 100644 --- a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -1267,7 +1267,7 @@ private boolean restartVpcInDomainRouter(DomainRouterJoinVO router, User user) { ActionEventUtils.onActionEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, Domain.ROOT_DOMAIN, EventTypes.EVENT_ROUTER_HEALTH_CHECKS, "Recreating router " + router.getUuid() + " by restarting VPC " + router.getVpcUuid()); - return vpcService.restartVpc(router.getVpcId(), true, false, user); + return vpcService.restartVpc(router.getVpcId(), true, false, false, user); } catch (Exception e) { s_logger.error("Failed to restart VPC for router recreation " + router.getVpcName() + " ,router " + router.getUuid(), e); @@ -1291,7 +1291,7 @@ private boolean restartGuestNetworkInDomainRouter(DomainRouterJoinVO router, Use ActionEventUtils.onActionEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, Domain.ROOT_DOMAIN, EventTypes.EVENT_ROUTER_HEALTH_CHECKS, "Recreating router " + router.getUuid() + " by restarting network " + router.getNetworkUuid()); - return networkService.restartNetwork(router.getNetworkId(), true, false, user); + return networkService.restartNetwork(router.getNetworkId(), true, false, false, user); } catch (Exception e) { s_logger.error("Failed to restart network " + router.getNetworkName() + " for router recreation " + router.getNetworkName(), e); diff --git a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java index 5752da2bf917..a2bad3d6f791 100644 --- a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java @@ -1712,13 +1712,14 @@ public boolean restartVpc(final RestartVPCCmd cmd) throws ConcurrentOperationExc final long vpcId = cmd.getId(); final boolean cleanUp = cmd.getCleanup(); final boolean makeRedundant = cmd.getMakeredundant(); + final boolean livePatch = cmd.getLivePatch(); final User callerUser = _accountMgr.getActiveUser(CallContext.current().getCallingUserId()); - return restartVpc(vpcId, cleanUp, makeRedundant, callerUser); + return restartVpc(vpcId, cleanUp, makeRedundant, livePatch, callerUser); } @Override @ActionEvent(eventType = EventTypes.EVENT_VPC_RESTART, eventDescription = "restarting vpc") - public boolean restartVpc(Long vpcId, boolean cleanUp, boolean makeRedundant, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { + public boolean restartVpc(Long vpcId, boolean cleanUp, boolean makeRedundant, boolean livePatch, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { Vpc vpc = getActiveVpc(vpcId); if (vpc == null) { final InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find Enabled VPC by id specified"); @@ -1761,7 +1762,11 @@ public boolean restartVpc(Long vpcId, boolean cleanUp, boolean makeRedundant, Us return true; } - restartVPCNetworks(vpcId, callerAccount, user, cleanUp); + if (cleanUp) { + livePatch = false; + } + + restartVPCNetworks(vpcId, callerAccount, user, cleanUp, livePatch); s_logger.debug("Starting VPC " + vpc + " as a part of VPC restart process without cleanup"); if (!startVpc(vpcId, false)) { @@ -1779,11 +1784,11 @@ public boolean restartVpc(Long vpcId, boolean cleanUp, boolean makeRedundant, Us } } - private void restartVPCNetworks(long vpcId, Account callerAccount, User callerUser, boolean cleanUp) throws InsufficientCapacityException, ResourceUnavailableException { + private void restartVPCNetworks(long vpcId, Account callerAccount, User callerUser, boolean cleanUp, boolean livePatch) throws InsufficientCapacityException, ResourceUnavailableException { List networks = _ntwkModel.listNetworksByVpc(vpcId); for (Network network: networks) { - if (network.isRestartRequired()) { - _ntwkMgr.restartNetwork(network.getId(), callerAccount, callerUser, cleanUp); + if (network.isRestartRequired() || livePatch) { + _ntwkMgr.restartNetwork(network.getId(), callerAccount, callerUser, cleanUp, livePatch); } } } diff --git a/server/src/main/java/com/cloud/server/ManagementServer.java b/server/src/main/java/com/cloud/server/ManagementServer.java index 4e58a4f55765..7ecb66503732 100644 --- a/server/src/main/java/com/cloud/server/ManagementServer.java +++ b/server/src/main/java/com/cloud/server/ManagementServer.java @@ -22,6 +22,7 @@ import com.cloud.storage.GuestOSVO; import com.cloud.utils.Pair; import com.cloud.utils.component.PluggableService; +import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; /** @@ -67,4 +68,6 @@ public interface ManagementServer extends ManagementService, PluggableService { public long getMemoryOrCpuCapacityByHost(Long hostId, short capacityType); + Pair updateSystemVM(VMInstanceVO systemVM, boolean forced); + } diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index 2a0734d7ec3a..03a806500de2 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -44,14 +44,21 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; import com.cloud.agent.api.PatchSystemVmAnswer; import com.cloud.agent.api.PatchSystemVmCommand; import com.cloud.agent.api.routing.NetworkElementCommand; +import com.cloud.agent.manager.Commands; import com.cloud.dc.DomainVlanMapVO; import com.cloud.dc.dao.DomainVlanMapDao; import com.cloud.exception.AgentUnavailableException; import com.cloud.network.Networks; +import com.cloud.utils.db.UUIDManager; +import com.cloud.utils.fsm.StateMachine2; +import com.cloud.vm.DomainRouterVO; import com.cloud.vm.NicVO; +import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.NicDao; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.affinity.AffinityGroupProcessor; @@ -766,12 +773,14 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServer, Configurable { public static final Logger s_logger = Logger.getLogger(ManagementServerImpl.class.getName()); + protected StateMachine2 _stateMachine; static final ConfigKey vmPasswordLength = new ConfigKey("Advanced", Integer.class, "vm.password.length", "6", "Specifies the length of a randomly generated password", false); static final ConfigKey sshKeyLength = new ConfigKey("Advanced", Integer.class, "ssh.key.length", "2048", "Specifies custom SSH key length (bit)", true, ConfigKey.Scope.Global); static final ConfigKey humanReadableSizes = new ConfigKey("Advanced", Boolean.class, "display.human.readable.sizes", "true", "Enables outputting human readable byte sizes to logs and usage records.", false, ConfigKey.Scope.Global); public static final ConfigKey customCsIdentifier = new ConfigKey("Advanced", String.class, "custom.cs.identifier", UUID.randomUUID().toString().split("-")[0].substring(4), "Custom identifier for the cloudstack installation", true, ConfigKey.Scope.Global); - private static final VirtualMachine.Type []systemVmTypes = { VirtualMachine.Type.SecondaryStorageVm, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.DomainRouter }; + private static final VirtualMachine.Type []systemVmTypes = { VirtualMachine.Type.SecondaryStorageVm, VirtualMachine.Type.ConsoleProxy}; + //, VirtualMachine.Type.DomainRouter }; @Inject public AccountManager _accountMgr; @@ -909,10 +918,15 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe private DomainVlanMapDao _domainVlanMapDao; @Inject private NicDao nicDao; + @Inject + DomainRouterDao routerDao; + @Inject + public UUIDManager uuidMgr; private LockControllerListener _lockControllerListener; private final ScheduledExecutorService _eventExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("EventChecker")); private final ScheduledExecutorService _alertExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("AlertChecker")); + private static final int patchCommandTimeout = 600000; private Map _configs; @@ -952,6 +966,7 @@ public void setAffinityGroupProcessors(final List affini public ManagementServerImpl() { setRunLevel(ComponentLifecycle.RUN_LEVEL_APPLICATION_MAINLOOP); + setStateMachine(); } public List getUserAuthenticators() { @@ -1010,6 +1025,10 @@ public boolean configure(final String name, final Map params) th return true; } + private void setStateMachine() { + _stateMachine = VirtualMachine.State.getStateMachine(); + } + @Override public boolean start() { s_logger.info("Startup CloudStack management server..."); @@ -4656,7 +4675,7 @@ public Pair patchSystemVM(PatchSystemVMCmd cmd) { final VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(systemVmId, systemVmTypes); if (systemVm == null) { - throw new InvalidParameterValueException("Unable to find SystemVm with id " + systemVmId); + throw new InvalidParameterValueException(String.format("Unable to find SystemVm with id %s. patchSystemVm API can be used to patch CPVM / SSVM only.", systemVmId)); } return updateSystemVM(systemVm, forced); @@ -4676,7 +4695,7 @@ private String getControlIp(final long systemVmId) { } if (controlIpAddress == null) { - s_logger.warn("Unable to find systemVm's control ip in its attached NICs!. systemVmId: " + systemVmId); + s_logger.warn(String.format("Unable to find systemVm's control ip in its attached NICs!. systemVmId: %s", systemVmId)); VMInstanceVO systemVM = _vmInstanceDao.findById(systemVmId); return systemVM.getPrivateIpAddress(); } @@ -4684,30 +4703,53 @@ private String getControlIp(final long systemVmId) { return controlIpAddress; } - private Pair updateSystemVM(VMInstanceVO systemVM, boolean forced) { + public Pair updateSystemVM(VMInstanceVO systemVM, boolean forced) { + String msg = String.format("Unable to patch SystemVM: %s as it is not in Running state. Please destroy and recreate the SystemVM.", systemVM); + if (systemVM.getState() != State.Running) { + s_logger.error(msg); + return new Pair<>(false, msg); + } return patchSystemVm(systemVM, forced); } + private boolean updateRouterDetails(Long routerId, String scriptVersion, String templateVersion) { + DomainRouterVO router = routerDao.findById(routerId); + if (router == null) { + throw new CloudRuntimeException(String.format("Failed to find router with id: %s", routerId)); + } + router.setTemplateVersion(templateVersion); + router.setScriptsVersion(scriptVersion); + return routerDao.update(routerId, router); + } + private Pair patchSystemVm(VMInstanceVO systemVM, boolean forced) { - PatchSystemVmAnswer answer = new PatchSystemVmAnswer(); + PatchSystemVmAnswer answer; final PatchSystemVmCommand command = new PatchSystemVmCommand(); command.setAccessDetail(NetworkElementCommand.ROUTER_IP, getControlIp(systemVM.getId())); command.setAccessDetail(NetworkElementCommand.ROUTER_NAME, systemVM.getInstanceName()); command.setForced(forced); try { - answer = (PatchSystemVmAnswer) _agentMgr.send(systemVM.getHostId(), command); + Commands cmds = new Commands(Command.OnError.Stop); + cmds.addCommand(command); + Answer[] answers = _agentMgr.send(systemVM.getHostId(), cmds, patchCommandTimeout); + answer = (PatchSystemVmAnswer) answers[0]; if (!answer.getResult()) { String errMsg = String.format("Failed to patch systemVM %s due to %s", systemVM.getInstanceName(), answer.getDetails()); s_logger.error(errMsg); return new Pair<>(false, errMsg); } - } catch (AgentUnavailableException | OperationTimedoutException e) { String errMsg = "SystemVM live patch failed"; s_logger.error(errMsg, e); return new Pair<>(false, String.format("%s due to: %s", errMsg, e.getMessage())); } - s_logger.info(String.format("Successfully patch system VM %s", systemVM.getInstanceName())); + s_logger.info(String.format("Successfully patched system VM %s", systemVM.getInstanceName())); + if (systemVM.getType() == VirtualMachine.Type.DomainRouter) { + boolean updated = updateRouterDetails(systemVM.getId(), answer.getScriptsVersion(), answer.getTemplateVersion()); + if (!updated) { + s_logger.warn("Failed to update router's script and template version details"); + } + } return new Pair<>(true, answer.getDetails()); } diff --git a/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java b/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java index 728effa8b764..e6082adb7d34 100644 --- a/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java @@ -214,7 +214,7 @@ public boolean deleteNetwork(long networkId, boolean forced) { } @Override - public boolean restartNetwork(Long networkId, boolean cleanup, boolean makeRedundant, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { + public boolean restartNetwork(Long networkId, boolean cleanup, boolean makeRedundant, boolean livePatch, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { return false; } @@ -760,7 +760,7 @@ public NetworkProfile convertNetworkToNetworkProfile(long networkId) { * @see com.cloud.network.NetworkManager#restartNetwork(java.lang.Long, com.cloud.user.Account, com.cloud.user.User, boolean) */ @Override - public boolean restartNetwork(Long networkId, Account callerAccount, User callerUser, boolean cleanup) throws ConcurrentOperationException, + public boolean restartNetwork(Long networkId, Account callerAccount, User callerUser, boolean cleanup, boolean livePatch) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { // TODO Auto-generated method stub return false; diff --git a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh index 324f92e90859..f193b4541fe1 100755 --- a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh +++ b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh @@ -37,7 +37,10 @@ setup_console_proxy() { enable_irqbalance 0 rm -f /etc/logrotate.d/cloud - setup_certificates + timeout 600 setup_certificates + if [ $? -gt 0 ]; then + log_it "Failed to setup CA Certificate for $TYPE" + fi } setup_console_proxy diff --git a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh index a34e671ba948..83cdb9f5b3dd 100755 --- a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh +++ b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh @@ -66,7 +66,10 @@ CORS setup_ntp rm -f /etc/logrotate.d/cloud - setup_certificates + timeout 600 setup_certificates + if [ $? -gt 0 ]; then + log_it "Failed to setup CA Certificate for $TYPE" + fi } setup_secstorage diff --git a/systemvm/patch-sysvms.sh b/systemvm/patch-sysvms.sh index 31478d7269ae..ee3c78a6270a 100644 --- a/systemvm/patch-sysvms.sh +++ b/systemvm/patch-sysvms.sh @@ -62,13 +62,18 @@ restart_services() { while IFS= read -r line do echo "$line" - systemctl restart "$line" - sleep 5 - systemctl is-active --quiet "$line" - if [ $? -gt 0 ]; then - echo "Failed to start "$line" service. Patch Failed. Restoring backup" >> $logfile - restore_backup - patchfailed=1 + for svc in ${line}; do + systemctl restart "$svc" + sleep 5 + systemctl is-active --quiet "$svc" + if [ $? -gt 0 ]; then + echo "Failed to start "$svc" service. Patch Failed. Retrying again" >> $logfile + restore_backup + patchfailed=1 + break + fi + done + if [ $patchfailed == 1 ]; then break fi done < "$svcfile" diff --git a/utils/src/main/java/com/cloud/utils/script/Script.java b/utils/src/main/java/com/cloud/utils/script/Script.java index 13845cda3a0a..931e922b597c 100644 --- a/utils/src/main/java/com/cloud/utils/script/Script.java +++ b/utils/src/main/java/com/cloud/utils/script/Script.java @@ -320,7 +320,7 @@ public String call() { try { _logger.trace("Checking exit value of process"); _process.exitValue(); - _logger.trace("Script ran within the alloted time"); + _logger.trace("Script ran within the allocated time"); } catch (IllegalThreadStateException e) { _logger.warn("Interrupting script."); _isTimeOut = true; From da7db395e25e889121be587066d2fc59c5df849c Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Fri, 31 Dec 2021 14:40:54 +0530 Subject: [PATCH 34/68] remove all references of systemvm.iso --- client/pom.xml | 26 ------------------- debian/cloudstack-common.install | 1 - packaging/centos7/cloud.spec | 2 +- packaging/centos8/cloud.spec | 2 +- packaging/suse15/cloud.spec | 2 +- .../vmware/resource/VmwareResource.java | 6 ----- scripts/vm/hypervisor/xenserver/xcposs/patch | 2 +- .../vm/hypervisor/xenserver/xcpserver/patch | 2 +- .../vm/hypervisor/xenserver/xenserver56/patch | 2 +- .../hypervisor/xenserver/xenserver56fp1/patch | 2 +- .../vm/hypervisor/xenserver/xenserver60/patch | 2 +- .../vm/hypervisor/xenserver/xenserver62/patch | 2 +- .../vm/hypervisor/xenserver/xenserver65/patch | 2 +- scripts/vm/systemvm/injectkeys.sh | 8 ------ .../consoleproxy/ConsoleProxyManagerImpl.java | 2 +- .../cloud/server/ConfigurationServerImpl.java | 5 +--- .../SecondaryStorageManagerImpl.java | 2 +- systemvm/pom.xml | 25 ------------------ tools/appliance/build.sh | 4 +-- 19 files changed, 15 insertions(+), 84 deletions(-) diff --git a/client/pom.xml b/client/pom.xml index eea178b9e1f2..73ccecedf873 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -866,32 +866,6 @@ - - - maven-antrun-plugin - 1.7 - - - - copy-systemvm - process-resources - - run - - - - - - - - - - - - - - diff --git a/debian/cloudstack-common.install b/debian/cloudstack-common.install index 9a9cf3bbc09f..8991abd02042 100644 --- a/debian/cloudstack-common.install +++ b/debian/cloudstack-common.install @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -/usr/share/cloudstack-common/vms/systemvm.iso /usr/share/cloudstack-common/scripts/installer/* /usr/share/cloudstack-common/scripts/network/* /usr/share/cloudstack-common/scripts/storage/* diff --git a/packaging/centos7/cloud.spec b/packaging/centos7/cloud.spec index b248cfc3323e..96915a1660ab 100644 --- a/packaging/centos7/cloud.spec +++ b/packaging/centos7/cloud.spec @@ -602,7 +602,7 @@ pip3 install --upgrade urllib3 %attr(0755,root,root) %{_datadir}/%{name}-common/scripts %attr(0755,root,root) /usr/bin/cloudstack-sccs # TODO: Remove systemvm.iso -%attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso +#%attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso %attr(0644, root, root) %{_datadir}/%{name}-common/vms/agent.zip %attr(0644, root, root) %{_datadir}/%{name}-common/vms/cloud-scripts.tgz %attr(0644, root, root) %{_datadir}/%{name}-common/vms/patch-sysvms.sh diff --git a/packaging/centos8/cloud.spec b/packaging/centos8/cloud.spec index 37a374d57e08..35e0e8d53578 100644 --- a/packaging/centos8/cloud.spec +++ b/packaging/centos8/cloud.spec @@ -590,7 +590,7 @@ pip install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz %attr(0755,root,root) %{_datadir}/%{name}-common/scripts %attr(0755,root,root) /usr/bin/cloudstack-sccs # TODO: Remove systemvm.iso -%attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso +#%attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso %attr(0644, root, root) %{_datadir}/%{name}-common/vms/agent.zip %attr(0644, root, root) %{_datadir}/%{name}-common/vms/cloud-scripts.tgz %attr(0644, root, root) %{_datadir}/%{name}-common/vms/patch-sysvms.sh diff --git a/packaging/suse15/cloud.spec b/packaging/suse15/cloud.spec index 23bce9fc92e1..bfdfa4826a1a 100644 --- a/packaging/suse15/cloud.spec +++ b/packaging/suse15/cloud.spec @@ -584,7 +584,7 @@ pip install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz %attr(0755,root,root) %{_datadir}/%{name}-common/scripts %attr(0755,root,root) /usr/bin/cloudstack-sccs # TODO: Remove systemvm.iso -%attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso +#%attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso %attr(0644, root, root) %{_datadir}/%{name}-common/vms/agent.zip %attr(0644, root, root) %{_datadir}/%{name}-common/vms/cloud-scripts.tgz %attr(0644, root, root) %{_datadir}/%{name}-common/vms/patch-sysvms.sh diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 6dab0721e86c..f759d118db17 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -2130,7 +2130,6 @@ protected StartAnswer execute(StartCommand cmd) { String msg = "secondary storage for dc " + _dcId + " is not ready yet?"; throw new Exception(msg); } - mgr.prepareSecondaryStorageStore(secStoreUrl, secStoreId); ManagedObjectReference morSecDs = prepareSecondaryDatastoreOnHost(secStoreUrl); if (morSecDs == null) { @@ -4463,10 +4462,6 @@ protected Answer execute(PrepareForMigrationCommand cmd) { throw new Exception(msg); } - if (vm.getType() != VirtualMachine.Type.User) { - mgr.prepareSecondaryStorageStore(secStoreUrl, secStoreId); - } - ManagedObjectReference morSecDs = prepareSecondaryDatastoreOnHost(secStoreUrl); if (morSecDs == null) { String msg = "Failed to prepare secondary storage on host, secondary store url: " + secStoreUrl; @@ -7428,7 +7423,6 @@ private List relocateVirtualMachine(final VmwareHypervisorHost h String msg = "secondary storage for dc " + _dcId + " is not ready yet?"; throw new Exception(msg); } - mgr.prepareSecondaryStorageStore(secStoreUrl, secStoreId); ManagedObjectReference morSecDs = prepareSecondaryDatastoreOnSpecificHost(secStoreUrl, targetHyperHost); if (morSecDs == null) { throw new Exception(String.format("Failed to prepare secondary storage on host, secondary store url: %s", secStoreUrl)); diff --git a/scripts/vm/hypervisor/xenserver/xcposs/patch b/scripts/vm/hypervisor/xenserver/xcposs/patch index f855c660d3ce..4686e67fe0a7 100644 --- a/scripts/vm/hypervisor/xenserver/xcposs/patch +++ b/scripts/vm/hypervisor/xenserver/xcposs/patch @@ -31,7 +31,7 @@ vmops=..,0755,/usr/lib/xcp/plugins ovsgre=..,0755,/usr/lib/xcp/plugins ovstunnel=..,0755,/usr/lib/xcp/plugins vmopsSnapshot=..,0755,/usr/lib/xcp/plugins -systemvm.iso=../../../../../vms,0644,/usr/share/xcp/packages/iso/ +#systemvm.iso=../../../../../vms,0644,/usr/share/xcp/packages/iso/ agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xcpserver/patch b/scripts/vm/hypervisor/xenserver/xcpserver/patch index 9768cba296da..da6ce60b7f68 100644 --- a/scripts/vm/hypervisor/xenserver/xcpserver/patch +++ b/scripts/vm/hypervisor/xenserver/xcpserver/patch @@ -31,7 +31,7 @@ NFSSR.py=/opt/xensource/sm vmops=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins -systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xenserver56/patch b/scripts/vm/hypervisor/xenserver/xenserver56/patch index 8a784ae21e64..fd844b4b6b05 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver56/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver56/patch @@ -30,7 +30,7 @@ NFSSR.py=/opt/xensource/sm vmops=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins -systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch b/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch index 93d2e4dee6ec..2a0f4b8aac78 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch @@ -30,7 +30,7 @@ NFSSR.py=/opt/xensource/sm vmops=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins -systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xenserver60/patch b/scripts/vm/hypervisor/xenserver/xenserver60/patch index 0271d06f5cf4..e32be41affa6 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver60/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver60/patch @@ -34,7 +34,7 @@ cloudstack_plugins.conf=..,0644,/etc/xensource cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins -systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xenserver62/patch b/scripts/vm/hypervisor/xenserver/xenserver62/patch index 5fda3aff5514..9bf9b9bdac23 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver62/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver62/patch @@ -35,7 +35,7 @@ cloudstack_plugins.conf=..,0644,/etc/xensource cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins cloud-plugin-storage=..,0755,/etc/xapi.d/plugins -systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xenserver65/patch b/scripts/vm/hypervisor/xenserver/xenserver65/patch index 5fda3aff5514..9bf9b9bdac23 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver65/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver65/patch @@ -35,7 +35,7 @@ cloudstack_plugins.conf=..,0644,/etc/xensource cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins cloud-plugin-storage=..,0755,/etc/xapi.d/plugins -systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso +#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/systemvm/injectkeys.sh b/scripts/vm/systemvm/injectkeys.sh index c05d232c0e7c..747fb07c5840 100755 --- a/scripts/vm/systemvm/injectkeys.sh +++ b/scripts/vm/systemvm/injectkeys.sh @@ -24,14 +24,8 @@ set -e TMP=/tmp -MOUNTPATH=${HOME}/systemvm_mnt -TMPDIR=${TMP}/cloud/systemvm umask 022 -clean_up() { - $SUDO umount $MOUNTPATH -} - copy_priv_key() { local newprivkey=$1 diff -q $newprivkey $(dirname $0)/id_rsa.cloud && return 0 @@ -45,8 +39,6 @@ then SUDO="sudo -n " fi -$SUDO mkdir -p $MOUNTPATH - [ $# -ne 1 ] && echo "Usage: $(basename $0) " && exit 3 newprivkey=$1 [ ! -f $newprivkey ] && echo "$(basename $0): Could not open $newprivkey" && exit 3 diff --git a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 40c6363ce169..c97646bd6fbf 100644 --- a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -1284,7 +1284,7 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl buf.append(" dns2=").append(dc.getDns2()); } - VirtualMachineGuru.appendCertificateDetails(buf, certificate); + //VirtualMachineGuru.appendCertificateDetails(buf, certificate); String bootArgs = buf.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug("Boot Args for " + profile + ": " + bootArgs); diff --git a/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java b/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java index b28e3de05592..f6e4d517ea84 100644 --- a/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java @@ -742,13 +742,10 @@ protected void copyPrivateKeyToHosts(String publicKeyPath, String privKeyPath) { s_logger.info("Trying to copy private keys to hosts"); String injectScript = getInjectScript(); String scriptPath = Script.findScript("", injectScript); - String systemVmIsoPath = Script.findScript("", "vms/systemvm.iso"); if (scriptPath == null) { throw new CloudRuntimeException("Unable to find key inject script " + injectScript); } - if (systemVmIsoPath == null) { - throw new CloudRuntimeException("Unable to find systemvm iso vms/systemvm.iso"); - } + Script command = null; if(isOnWindows()) { command = new Script("python", s_logger); diff --git a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java index fb300cbbeb93..a960f2a63bde 100644 --- a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java +++ b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java @@ -1165,7 +1165,7 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl String nfsVersion = imageStoreDetailsUtil != null ? imageStoreDetailsUtil.getNfsVersion(secStore.getId()) : null; buf.append(" nfsVersion=").append(nfsVersion); - VirtualMachineGuru.appendCertificateDetails(buf, certificate); + //VirtualMachineGuru.appendCertificateDetails(buf, certificate); String bootArgs = buf.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug(String.format("Boot args for machine profile [%s]: [%s].", profile.toString(), bootArgs)); diff --git a/systemvm/pom.xml b/systemvm/pom.xml index 929f948abd1d..69e971b74715 100644 --- a/systemvm/pom.xml +++ b/systemvm/pom.xml @@ -144,31 +144,6 @@ - - org.codehaus.mojo - exec-maven-plugin - 1.2.1 - - - package - - exec - - - - - ${mkisofs} - dist - - -quiet - -r - -o - systemvm.iso - agent.zip - cloud-scripts.tgz - - - diff --git a/tools/appliance/build.sh b/tools/appliance/build.sh index 285d818c0c75..5a97c9dbf6b6 100755 --- a/tools/appliance/build.sh +++ b/tools/appliance/build.sh @@ -348,9 +348,9 @@ function main() { packer_build # process the disk at dist -# kvm_export + kvm_export # ovm_export -# xen_server_export + xen_server_export vmware_export # hyperv_export rm -f "dist/${appliance}" From ec5d082d339f12fb20ca64d3a882307bf9777be2 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Mon, 3 Jan 2022 12:59:34 +0530 Subject: [PATCH 35/68] Fix keystore-cert-import invocation + refactor cert timeout in CP/SS VMs --- .../VirtualRoutingResource.java | 6 +- scripts/util/keystore-cert-import | 35 +++++---- .../consoleproxy/ConsoleProxyManagerImpl.java | 2 +- .../discoverer/LibvirtServerDiscoverer.java | 78 ++++++++++--------- .../SecondaryStorageManagerImpl.java | 2 +- .../opt/cloud/bin/setup/consoleproxy.sh | 2 +- .../debian/opt/cloud/bin/setup/secstorage.sh | 2 +- .../main/java/com/cloud/utils/FileUtil.java | 28 ++++--- .../com/cloud/utils/ssh/SSHCmdHelper.java | 4 +- 9 files changed, 85 insertions(+), 74 deletions(-) diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java index 54b9d38a9625..2690ec4c8076 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java @@ -34,6 +34,8 @@ import javax.naming.ConfigurationException; +import com.cloud.utils.PasswordGenerator; +import org.apache.cloudstack.ca.CAManager; import org.apache.cloudstack.ca.SetupCertificateAnswer; import org.apache.cloudstack.ca.SetupCertificateCommand; import org.apache.cloudstack.ca.SetupKeyStoreCommand; @@ -174,11 +176,13 @@ private Answer execute(final SetupKeyStoreCommand cmd) { } private Answer execute(final SetupCertificateCommand cmd) { - final String args = String.format("/usr/local/cloud/systemvm/conf/agent.properties " + + final String args = String.format("/usr/local/cloud/systemvm/conf/agent.properties %s %s " + "/usr/local/cloud/systemvm/conf/%s %s " + "/usr/local/cloud/systemvm/conf/%s \"%s\" " + "/usr/local/cloud/systemvm/conf/%s \"%s\" " + "/usr/local/cloud/systemvm/conf/%s \"%s\"", + PasswordGenerator.generateRandomPassword(16), + CAManager.CertValidityPeriod.value(), KeyStoreUtils.KS_FILENAME, KeyStoreUtils.SSH_MODE, KeyStoreUtils.CERT_FILENAME, diff --git a/scripts/util/keystore-cert-import b/scripts/util/keystore-cert-import index 8e63e9509cc0..7c750a412eb8 100755 --- a/scripts/util/keystore-cert-import +++ b/scripts/util/keystore-cert-import @@ -32,24 +32,25 @@ ALIAS="cloud" SYSTEM_FILE="/var/cache/cloud/cmdline" LIBVIRTD_FILE="/etc/libvirt/libvirtd.conf" -# Re-use existing password or use the one provided -if [ -f "$PROPS_FILE" ]; then - OLD_PASS=$(sed -n '/keystore.passphrase/p' "$PROPS_FILE" 2>/dev/null | sed 's/keystore.passphrase=//g' 2>/dev/null) - if [ ! -z "${OLD_PASS// }" ]; then - KS_PASS="$OLD_PASS" - else - sed -i "/keystore.passphrase.*/d" $PROPS_FILE 2> /dev/null || true - echo "keystore.passphrase=$KS_PASS" >> $PROPS_FILE - fi +if [ ! -f "$LIBVIRTD_FILE" ]; then + # Re-use existing password or use the one provided + if [ -f "$PROPS_FILE" ]; then + OLD_PASS=$(sed -n '/keystore.passphrase/p' "$PROPS_FILE" 2>/dev/null | sed 's/keystore.passphrase=//g' 2>/dev/null) + if [ ! -z "${OLD_PASS// }" ]; then + KS_PASS="$OLD_PASS" + else + sed -i "/keystore.passphrase.*/d" $PROPS_FILE 2> /dev/null || true + echo "keystore.passphrase=$KS_PASS" >> $PROPS_FILE + fi + fi + + if [ -f "$KS_FILE" ]; then + keytool -delete -noprompt -alias "$ALIAS" -keystore "$KS_FILE" -storepass "$KS_PASS" > /dev/null 2>&1 || true + fi + + CN=$(hostname --fqdn) + keytool -genkey -storepass "$KS_PASS" -keypass "$KS_PASS" -alias "$ALIAS" -keyalg RSA -validity "$KS_VALIDITY" -dname cn="$CN",ou="cloudstack",o="cloudstack",c="cloudstack" -keystore "$KS_FILE" > /dev/null 2>&1 fi - -if [ -f "$KS_FILE" ]; then - keytool -delete -noprompt -alias "$ALIAS" -keystore "$KS_FILE" -storepass "$KS_PASS" > /dev/null 2>&1 || true -fi - -CN=$(hostname --fqdn) -keytool -genkey -storepass "$KS_PASS" -keypass "$KS_PASS" -alias "$ALIAS" -keyalg RSA -validity "$KS_VALIDITY" -dname cn="$CN",ou="cloudstack",o="cloudstack",c="cloudstack" -keystore "$KS_FILE" > /dev/null 2>&1 - # Find keystore password KS_PASS=$(sed -n '/keystore.passphrase/p' "$PROPS_FILE" 2>/dev/null | sed 's/keystore.passphrase=//g' 2>/dev/null) diff --git a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index c97646bd6fbf..40c6363ce169 100644 --- a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -1284,7 +1284,7 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl buf.append(" dns2=").append(dc.getDns2()); } - //VirtualMachineGuru.appendCertificateDetails(buf, certificate); + VirtualMachineGuru.appendCertificateDetails(buf, certificate); String bootArgs = buf.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug("Boot Args for " + profile + ": " + bootArgs); diff --git a/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java b/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java index 818c14f5b25f..a67925bbef45 100644 --- a/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java +++ b/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java @@ -16,26 +16,6 @@ // under the License. package com.cloud.hypervisor.kvm.discoverer; -import java.net.InetAddress; -import java.net.URI; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import javax.inject.Inject; -import javax.naming.ConfigurationException; - -import org.apache.cloudstack.agent.lb.IndirectAgentLB; -import org.apache.cloudstack.ca.CAManager; -import org.apache.cloudstack.ca.SetupCertificateCommand; -import org.apache.cloudstack.direct.download.DirectDownloadManager; -import org.apache.cloudstack.framework.ca.Certificate; -import org.apache.cloudstack.utils.security.KeyStoreUtils; -import org.apache.log4j.Logger; - import com.cloud.agent.AgentManager; import com.cloud.agent.Listener; import com.cloud.agent.api.AgentControlAnswer; @@ -68,6 +48,24 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.ssh.SSHCmdHelper; import com.trilead.ssh2.Connection; +import org.apache.cloudstack.agent.lb.IndirectAgentLB; +import org.apache.cloudstack.ca.CAManager; +import org.apache.cloudstack.ca.SetupCertificateCommand; +import org.apache.cloudstack.direct.download.DirectDownloadManager; +import org.apache.cloudstack.framework.ca.Certificate; +import org.apache.cloudstack.utils.security.KeyStoreUtils; +import org.apache.log4j.Logger; + +import javax.inject.Inject; +import javax.naming.ConfigurationException; +import java.net.InetAddress; +import java.net.URI; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; import static com.cloud.configuration.ConfigurationManagerImpl.ADD_HOST_ON_SERVICE_RESTART_KVM; @@ -163,6 +161,7 @@ private void setupAgentSecurity(final Connection sshConnection, final String age validityPeriod = 1; } + String keystorePassword = PasswordGenerator.generateRandomPassword(16); final SSHCmdHelper.SSHCmdResult keystoreSetupResult = SSHCmdHelper.sshExecuteCmdWithResult(sshConnection, String.format("sudo /usr/share/cloudstack-common/scripts/util/%s " + "/etc/cloudstack/agent/agent.properties " + @@ -171,7 +170,7 @@ private void setupAgentSecurity(final Connection sshConnection, final String age "/etc/cloudstack/agent/%s", KeyStoreUtils.KS_SETUP_SCRIPT, KeyStoreUtils.KS_FILENAME, - PasswordGenerator.generateRandomPassword(16), + keystorePassword, validityPeriod, KeyStoreUtils.CSR_FILENAME)); @@ -186,21 +185,23 @@ private void setupAgentSecurity(final Connection sshConnection, final String age final SetupCertificateCommand certificateCommand = new SetupCertificateCommand(certificate); final SSHCmdHelper.SSHCmdResult setupCertResult = SSHCmdHelper.sshExecuteCmdWithResult(sshConnection, - String.format("sudo /usr/share/cloudstack-common/scripts/util/%s " + - "/etc/cloudstack/agent/agent.properties " + - "/etc/cloudstack/agent/%s %s " + - "/etc/cloudstack/agent/%s \"%s\" " + - "/etc/cloudstack/agent/%s \"%s\" " + - "/etc/cloudstack/agent/%s \"%s\"", - KeyStoreUtils.KS_IMPORT_SCRIPT, - KeyStoreUtils.KS_FILENAME, - KeyStoreUtils.SSH_MODE, - KeyStoreUtils.CERT_FILENAME, - certificateCommand.getEncodedCertificate(), - KeyStoreUtils.CACERT_FILENAME, - certificateCommand.getEncodedCaCertificates(), - KeyStoreUtils.PKEY_FILENAME, - certificateCommand.getEncodedPrivateKey())); + String.format("sudo /usr/share/cloudstack-common/scripts/util/%s " + + "/etc/cloudstack/agent/agent.properties %s %s " + + " /etc/cloudstack/agent/%s %s " + + "/etc/cloudstack/agent/%s \"%s\" " + + "/etc/cloudstack/agent/%s \"%s\" " + + "/etc/cloudstack/agent/%s \"%s\"", + KeyStoreUtils.KS_IMPORT_SCRIPT, + keystorePassword, + validityPeriod, + KeyStoreUtils.KS_FILENAME, + KeyStoreUtils.SSH_MODE, + KeyStoreUtils.CERT_FILENAME, + certificateCommand.getEncodedCertificate(), + KeyStoreUtils.CACERT_FILENAME, + certificateCommand.getEncodedCaCertificates(), + KeyStoreUtils.PKEY_FILENAME, + certificateCommand.getEncodedPrivateKey())); if (setupCertResult != null && !setupCertResult.isSuccess()) { throw new CloudRuntimeException("Failed to setup certificate in the KVM agent's keystore file, please see logs and configure manually!"); @@ -213,7 +214,7 @@ private void setupAgentSecurity(final Connection sshConnection, final String age @Override public Map> - find(long dcId, Long podId, Long clusterId, URI uri, String username, String password, List hostTags) throws DiscoveryException { + find(long dcId, Long podId, Long clusterId, URI uri, String username, String password, List hostTags) throws DiscoveryException { boolean isUefiSupported = false; ClusterVO cluster = _clusterDao.findById(clusterId); @@ -256,6 +257,7 @@ private void setupAgentSecurity(final Connection sshConnection, final String age } } + s_logger.info("PEARL - agent IP: "+ agentIp); sshConnection = new Connection(agentIp, 22); sshConnection.connect(null, 60000, 60000); @@ -473,7 +475,7 @@ public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { String hostOs = ssCmd.getHostDetails().get("Host.OS"); if (!hostOsInCluster.equalsIgnoreCase(hostOs)) { throw new IllegalArgumentException("Can't add host: " + firstCmd.getPrivateIpAddress() + " with hostOS: " + hostOs + " into a cluster," + - "in which there are " + hostOsInCluster + " hosts added"); + "in which there are " + hostOsInCluster + " hosts added"); } } diff --git a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java index a960f2a63bde..fb300cbbeb93 100644 --- a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java +++ b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java @@ -1165,7 +1165,7 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl String nfsVersion = imageStoreDetailsUtil != null ? imageStoreDetailsUtil.getNfsVersion(secStore.getId()) : null; buf.append(" nfsVersion=").append(nfsVersion); - //VirtualMachineGuru.appendCertificateDetails(buf, certificate); + VirtualMachineGuru.appendCertificateDetails(buf, certificate); String bootArgs = buf.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug(String.format("Boot args for machine profile [%s]: [%s].", profile.toString(), bootArgs)); diff --git a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh index f193b4541fe1..eddbc9daf9a0 100755 --- a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh +++ b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh @@ -37,7 +37,7 @@ setup_console_proxy() { enable_irqbalance 0 rm -f /etc/logrotate.d/cloud - timeout 600 setup_certificates + timeout 600 setup_certificates <( setup_certificates ) if [ $? -gt 0 ]; then log_it "Failed to setup CA Certificate for $TYPE" fi diff --git a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh index 83cdb9f5b3dd..c16b53d3cbd9 100755 --- a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh +++ b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh @@ -66,7 +66,7 @@ CORS setup_ntp rm -f /etc/logrotate.d/cloud - timeout 600 setup_certificates + timeout 600 setup_certificates <( setup_certificates ) if [ $? -gt 0 ]; then log_it "Failed to setup CA Certificate for $TYPE" fi diff --git a/utils/src/main/java/com/cloud/utils/FileUtil.java b/utils/src/main/java/com/cloud/utils/FileUtil.java index 2121d3a7ae26..cc44c0b80570 100644 --- a/utils/src/main/java/com/cloud/utils/FileUtil.java +++ b/utils/src/main/java/com/cloud/utils/FileUtil.java @@ -38,18 +38,22 @@ public static void copyfile(File source, File destination) throws IOException { } public static void scpPatchFiles(String controlIp, String destPath, int sshPort, File pemFile, String[] files, String basePath) { - try { - List srcFiles = Arrays.asList(files); - srcFiles = srcFiles.stream() - .map(file -> basePath + file) // Using Lambda notation to update the entries - .collect(Collectors.toList()); - String[] newSrcFiles = srcFiles.toArray(new String[0]); - SshHelper.scpTo(controlIp, sshPort, "root", pemFile, null, - destPath, newSrcFiles, "0755"); - } catch (Exception e) { - String errMsg = "Failed to scp files to system VM"; - s_logger.error(errMsg, e); - throw new CloudRuntimeException(errMsg, e); + String errMsg = "Failed to scp files to system VM"; + List srcFiles = Arrays.asList(files); + srcFiles = srcFiles.stream() + .map(file -> basePath + file) // Using Lambda notation to update the entries + .collect(Collectors.toList()); + String[] newSrcFiles = srcFiles.toArray(new String[0]); + for (int retries = 3; retries > 0; retries--) { + try { + SshHelper.scpTo(controlIp, sshPort, "root", pemFile, null, + destPath, newSrcFiles, "0755"); + return; + } catch (Exception e) { + errMsg += ", retrying"; + s_logger.error(errMsg, e); + } } + throw new CloudRuntimeException(errMsg); } } diff --git a/utils/src/main/java/com/cloud/utils/ssh/SSHCmdHelper.java b/utils/src/main/java/com/cloud/utils/ssh/SSHCmdHelper.java index 41ee2edb4623..6621546859c9 100644 --- a/utils/src/main/java/com/cloud/utils/ssh/SSHCmdHelper.java +++ b/utils/src/main/java/com/cloud/utils/ssh/SSHCmdHelper.java @@ -241,8 +241,8 @@ public static SSHCmdResult sshExecuteCmdOneShot(com.trilead.ssh2.Connection sshC } return result; } catch (Exception e) { - s_logger.debug("Ssh executed failed", e); - throw new SshException("Ssh executed failed " + e.getMessage()); + s_logger.debug("SSH execution failed", e); + throw new SshException("SSH execution failed " + e.getMessage()); } finally { if (sshSession != null) sshSession.close(); From 6c190d127a9bbe849a15450977c2967c7debd141 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Mon, 3 Jan 2022 16:41:56 +0530 Subject: [PATCH 36/68] fix script timeout --- systemvm/debian/opt/cloud/bin/setup/common.sh | 2 +- systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh | 2 +- systemvm/debian/opt/cloud/bin/setup/secstorage.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/systemvm/debian/opt/cloud/bin/setup/common.sh b/systemvm/debian/opt/cloud/bin/setup/common.sh index be0b1c46b890..3f4817a07795 100755 --- a/systemvm/debian/opt/cloud/bin/setup/common.sh +++ b/systemvm/debian/opt/cloud/bin/setup/common.sh @@ -599,7 +599,7 @@ setup_certificates() { privatekey=$(echo "$PRIVATEKEY" | base64 -d) kspass=$(echo "$KEYSTORE_PSSWD"| base64 -d) ksvalidity="$KS_VALIDITY" - /opt/cloud/bin/keystore-cert-import /usr/local/cloud/systemvm/conf/agent.properties $kspass $ksvalidity \ + timeout 600 /opt/cloud/bin/keystore-cert-import /usr/local/cloud/systemvm/conf/agent.properties $kspass $ksvalidity \ /usr/local/cloud/systemvm/conf/cloud.jks ssh /usr/local/cloud/systemvm/conf/cloud.crt \ $certificate /usr/local/cloud/systemvm/conf/cloud.ca.crt $cacertificate /usr/local/cloud/systemvm/conf/cloud.key $privatekey } diff --git a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh index eddbc9daf9a0..f8fcb51d94cb 100755 --- a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh +++ b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh @@ -37,7 +37,7 @@ setup_console_proxy() { enable_irqbalance 0 rm -f /etc/logrotate.d/cloud - timeout 600 setup_certificates <( setup_certificates ) + setup_certificates if [ $? -gt 0 ]; then log_it "Failed to setup CA Certificate for $TYPE" fi diff --git a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh index c16b53d3cbd9..041853287a34 100755 --- a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh +++ b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh @@ -66,7 +66,7 @@ CORS setup_ntp rm -f /etc/logrotate.d/cloud - timeout 600 setup_certificates <( setup_certificates ) + setup_certificates if [ $? -gt 0 ]; then log_it "Failed to setup CA Certificate for $TYPE" fi From 3a279546a34336caee488db5f1dea5b089ed9302 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Wed, 5 Jan 2022 18:03:28 +0530 Subject: [PATCH 37/68] Refactor cert patching for systemVMs + update keystore-cert-import script + patch-sysvms script + remove patchSysvmCommand from networkelementcommand --- .gitignore | 1 + .../src/main/java/com/cloud/agent/Agent.java | 2 + .../cloud/agent/api/PatchSystemVmCommand.java | 31 ++++++++++- .../com/cloud/agent/api/StartCommand.java | 30 +++++++++++ .../VirtualRoutingResource.java | 10 ++-- .../com/cloud/resource/ServerResource.java | 2 + .../cloud/resource/ServerResourceBase.java | 4 +- .../java/com/cloud/vm/VirtualMachineGuru.java | 2 +- .../cloud/vm/VirtualMachineManagerImpl.java | 45 ++++++++++++++-- .../LibvirtPatchSystemVmCommandWrapper.java | 16 ++++-- .../wrapper/LibvirtStartCommandWrapper.java | 32 ++++++++++++ .../vmware/resource/VmwareResource.java | 16 ++++-- .../resource/CitrixResourceBase.java | 9 +--- .../CitrixNetworkElementCommandWrapper.java | 3 +- .../CitrixPatchSystemVmCommandWrapper.java | 17 +++++-- scripts/util/keystore-cert-import | 47 +++++++++++------ .../consoleproxy/ConsoleProxyManagerImpl.java | 5 +- .../discoverer/LibvirtServerDiscoverer.java | 6 +-- .../cloud/server/ManagementServerImpl.java | 1 + .../apache/cloudstack/ca/CAManagerImpl.java | 17 +++++-- .../com/cloud/consoleproxy/ConsoleProxy.java | 15 +++--- .../SecondaryStorageManagerImpl.java | 5 +- .../opt/cloud/bin/setup/cloud-early-config | 3 ++ systemvm/debian/opt/cloud/bin/setup/common.sh | 10 ++-- .../opt/cloud/bin/setup/consoleproxy.sh | 11 ++-- .../debian/opt/cloud/bin/setup/secstorage.sh | 8 +-- systemvm/patch-sysvms.sh | 51 +++++++++++-------- .../utils/security/KeyStoreUtils.java | 1 + 28 files changed, 300 insertions(+), 100 deletions(-) diff --git a/.gitignore b/.gitignore index b67dc8e6499f..011a4b005dce 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,7 @@ tools/cli/cloudmonkey/precache.py tools/marvin/marvin/cloudstackAPI/ tools/marvin/build/ tools/cli/build/ +tools/appliance/systemvmtemplate/packer_cache/ *.jar *.war *.mar diff --git a/agent/src/main/java/com/cloud/agent/Agent.java b/agent/src/main/java/com/cloud/agent/Agent.java index 4edfb7871a51..2d14b910ad6d 100644 --- a/agent/src/main/java/com/cloud/agent/Agent.java +++ b/agent/src/main/java/com/cloud/agent/Agent.java @@ -763,8 +763,10 @@ private Answer setupAgentCertificate(final SetupCertificateCommand cmd) { throw new CloudRuntimeException("Unable to save received agent client and ca certificates", e); } + String ksPassphrase = _shell.getPersistentProperty(null, KeyStoreUtils.KS_PASSPHRASE_PROPERTY); Script script = new Script(_keystoreCertImportPath, 300000, s_logger); script.add(agentFile.getAbsolutePath()); + script.add(ksPassphrase); script.add(keyStoreFile); script.add(KeyStoreUtils.AGENT_MODE); script.add(certFile); diff --git a/core/src/main/java/com/cloud/agent/api/PatchSystemVmCommand.java b/core/src/main/java/com/cloud/agent/api/PatchSystemVmCommand.java index b9ea2d62963b..29c5baca7f03 100644 --- a/core/src/main/java/com/cloud/agent/api/PatchSystemVmCommand.java +++ b/core/src/main/java/com/cloud/agent/api/PatchSystemVmCommand.java @@ -16,8 +16,12 @@ // under the License. package com.cloud.agent.api; -public class PatchSystemVmCommand extends GetDomRVersionCmd { +import java.util.HashMap; +import java.util.Map; + +public class PatchSystemVmCommand extends Command { boolean forced; + HashMap accessDetails = new HashMap(0); public boolean isForced() { return forced; @@ -26,4 +30,29 @@ public boolean isForced() { public void setForced(boolean forced) { this.forced = forced; } + + public void setAccessDetail(final Map details) { + if (details == null) { + return; + } + for (final Map.Entry detail : details.entrySet()) { + if (detail == null) { + continue; + } + setAccessDetail(detail.getKey(), detail.getValue()); + } + } + + public void setAccessDetail(final String name, final String value) { + accessDetails.put(name, value); + } + + public String getAccessDetail(final String name) { + return accessDetails.get(name); + } + + @Override + public boolean executeInSequence() { + return false; + } } diff --git a/core/src/main/java/com/cloud/agent/api/StartCommand.java b/core/src/main/java/com/cloud/agent/api/StartCommand.java index 24b0ac3787b5..3af11932588e 100644 --- a/core/src/main/java/com/cloud/agent/api/StartCommand.java +++ b/core/src/main/java/com/cloud/agent/api/StartCommand.java @@ -29,6 +29,12 @@ public class StartCommand extends Command { String hostIp; boolean executeInSequence = false; String secondaryStorage; + @LogLevel(LogLevel.Log4jLevel.Off) + private String certificate; + @LogLevel(LogLevel.Log4jLevel.Off) + private String privateKey = ""; + @LogLevel(LogLevel.Log4jLevel.Off) + private String caCertificates; public VirtualMachineTO getVirtualMachine() { return vm; @@ -64,4 +70,28 @@ public String getSecondaryStorage() { public void setSecondaryStorage(String secondary) { this.secondaryStorage = secondary; } + + public void setCertificate(String certificate) { + this.certificate = certificate; + } + + public void setPrivateKey(String privateKey) { + this.privateKey = privateKey; + } + + public void setCaCertificates(String caCertificates) { + this.caCertificates = caCertificates; + } + + public String getCertificate() { + return certificate; + } + + public String getPrivateKey() { + return privateKey; + } + + public String getCaCertificates() { + return caCertificates; + } } diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java index 2690ec4c8076..cddee33ac382 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java @@ -35,7 +35,6 @@ import javax.naming.ConfigurationException; import com.cloud.utils.PasswordGenerator; -import org.apache.cloudstack.ca.CAManager; import org.apache.cloudstack.ca.SetupCertificateAnswer; import org.apache.cloudstack.ca.SetupCertificateCommand; import org.apache.cloudstack.ca.SetupKeyStoreCommand; @@ -176,13 +175,18 @@ private Answer execute(final SetupKeyStoreCommand cmd) { } private Answer execute(final SetupCertificateCommand cmd) { - final String args = String.format("/usr/local/cloud/systemvm/conf/agent.properties %s %s " + + String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + if (!org.apache.commons.lang3.StringUtils.isEmpty(routerName) && (routerName.startsWith("s-") || routerName.startsWith("v-"))) { + _vrDeployer.createFileInVR(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.CERT_FILENAME, cmd.getCertificate()); + _vrDeployer.createFileInVR(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.CACERT_FILENAME, cmd.getCaCertificates()); + _vrDeployer.createFileInVR(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.PKEY_FILENAME, cmd.getPrivateKey()); + } + final String args = String.format("/usr/local/cloud/systemvm/conf/agent.properties %s " + "/usr/local/cloud/systemvm/conf/%s %s " + "/usr/local/cloud/systemvm/conf/%s \"%s\" " + "/usr/local/cloud/systemvm/conf/%s \"%s\" " + "/usr/local/cloud/systemvm/conf/%s \"%s\"", PasswordGenerator.generateRandomPassword(16), - CAManager.CertValidityPeriod.value(), KeyStoreUtils.KS_FILENAME, KeyStoreUtils.SSH_MODE, KeyStoreUtils.CERT_FILENAME, diff --git a/core/src/main/java/com/cloud/resource/ServerResource.java b/core/src/main/java/com/cloud/resource/ServerResource.java index 5571f33bb8a3..f2beb4a1845a 100644 --- a/core/src/main/java/com/cloud/resource/ServerResource.java +++ b/core/src/main/java/com/cloud/resource/ServerResource.java @@ -26,6 +26,7 @@ import com.cloud.agent.api.StartupCommand; import com.cloud.host.Host; import com.cloud.utils.component.Manager; +import org.apache.cloudstack.utils.security.KeyStoreUtils; import java.io.File; @@ -36,6 +37,7 @@ public interface ServerResource extends Manager { String[] srcFiles = new String[] { "agent.zip", "cloud-scripts.tgz" }; String[] newSrcFiles = new String[] { "agent.zip", "cloud-scripts.tgz", "patch-sysvms.sh" }; + String[] certificateFiles = new String[] {KeyStoreUtils.CERT_FILENAME, KeyStoreUtils.CACERT_FILENAME, KeyStoreUtils.PKEY_FILENAME}; String SSHKEYSPATH = "/root/.ssh"; String SSHPRVKEYPATH = SSHKEYSPATH + File.separator + "id_rsa.cloud"; diff --git a/core/src/main/java/com/cloud/resource/ServerResourceBase.java b/core/src/main/java/com/cloud/resource/ServerResourceBase.java index 80057779e249..d8db1fd64605 100644 --- a/core/src/main/java/com/cloud/resource/ServerResourceBase.java +++ b/core/src/main/java/com/cloud/resource/ServerResourceBase.java @@ -310,8 +310,8 @@ public boolean stop() { return true; } - public String calculateCurrentChecksum(String name) { - String cloudScriptsPath = Script.findScript("", "vms/cloud-scripts.tgz"); + public String calculateCurrentChecksum(String name, String path) { + String cloudScriptsPath = Script.findScript("", path); if (cloudScriptsPath == null) { throw new CloudRuntimeException(String.format("Unable to find cloudScripts path, cannot update SystemVM %s", name)); } diff --git a/engine/api/src/main/java/com/cloud/vm/VirtualMachineGuru.java b/engine/api/src/main/java/com/cloud/vm/VirtualMachineGuru.java index d6d7513fd5c6..f8032bf4b0e7 100644 --- a/engine/api/src/main/java/com/cloud/vm/VirtualMachineGuru.java +++ b/engine/api/src/main/java/com/cloud/vm/VirtualMachineGuru.java @@ -80,7 +80,7 @@ static String getEncodedMsPublicKey(String pubKey) { return base64EncodedPublicKey; } - private static String getEncodedString(String certificate) { + public static String getEncodedString(String certificate) { return Base64.getEncoder().encodeToString(certificate.replace("\n", KeyStoreUtils.CERT_NEWLINE_ENCODER).replace(" ", KeyStoreUtils.CERT_SPACE_ENCODER).getBytes(StandardCharsets.UTF_8)); } diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index 26b6bc38e173..2a9438198749 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -17,6 +17,7 @@ package com.cloud.vm; +import java.io.IOException; import java.net.URI; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -79,6 +80,7 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.cloudstack.utils.identity.ManagementServerNode; +import org.apache.cloudstack.utils.security.CertUtils; import org.apache.cloudstack.vm.UnmanagedVMsManager; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; @@ -551,7 +553,7 @@ public void advanceExpunge(final String vmUuid) throws ResourceUnavailableExcept advanceExpunge(vm); } - private boolean expungeCommandCanBypassHostMaintenance(VirtualMachine vm) { + private boolean isValidSystemVMType(VirtualMachine vm) { return VirtualMachine.Type.SecondaryStorageVm.equals(vm.getType()) || VirtualMachine.Type.ConsoleProxy.equals(vm.getType()); } @@ -603,7 +605,7 @@ protected void advanceExpunge(VMInstanceVO vm) throws ResourceUnavailableExcepti final Commands cmds = new Commands(Command.OnError.Stop); for (final Command volumeExpungeCommand : volumeExpungeCommands) { - volumeExpungeCommand.setBypassHostMaintenance(expungeCommandCanBypassHostMaintenance(vm)); + volumeExpungeCommand.setBypassHostMaintenance(isValidSystemVMType(vm)); cmds.addCommand(volumeExpungeCommand); } @@ -689,7 +691,7 @@ private void addAllExpungeCommandsFromList(List cmdList, Commands cmds, return; } for (final Command command : cmdList) { - command.setBypassHostMaintenance(expungeCommandCanBypassHostMaintenance(vm)); + command.setBypassHostMaintenance(isValidSystemVMType(vm)); if (s_logger.isTraceEnabled()) { s_logger.trace(String.format("Adding expunge command [%s] for VM [%s]", command.toString(), vm.toString())); } @@ -1191,8 +1193,23 @@ public void orchestrateStart(final String vmUuid, final Map sshAccessDetails = _networkMgr.getSystemVMAccessDetails(vm); + final Map ipAddressDetails = new HashMap<>(sshAccessDetails); + ipAddressDetails.remove(NetworkElementCommand.ROUTER_NAME); + + StartCommand command = new StartCommand(vmTO, dest.getHost(), getExecuteInSequence(vm.getHypervisorType())); + if (isValidSystemVMType(vm)) { + final Certificate certificate = caManager.issueCertificate(null, Arrays.asList(vmProfile.getHostName(), vmProfile.getInstanceName()), + new ArrayList<>(ipAddressDetails.values()), CAManager.CertValidityPeriod.value(), null); + try { + command.setCertificate(CertUtils.x509CertificateToPem(certificate.getClientCertificate())); + command.setCaCertificates(CertUtils.x509CertificatesToPem(certificate.getCaCertificates())); + command.setPrivateKey(CertUtils.privateKeyToPem(certificate.getPrivateKey())); + } catch (IOException e) { + throw new CloudRuntimeException("Failed to generate/setup certificates for system VM"); + } + } + cmds.addCommand(command); vmGuru.finalizeDeployment(cmds, vmProfile, dest, ctx); @@ -1243,6 +1260,24 @@ public void orchestrateStart(final String vmUuid, final Map 0; retries--) { + try { + final Certificate certificate = caManager.issueCertificate(null, Arrays.asList(vm.getHostName(), vm.getInstanceName()), + new ArrayList<>(ipAddressDetails.values()), CAManager.CertValidityPeriod.value(), null); + final boolean result = caManager.deployCertificate(vmHost, certificate, false, sshAccessDetails); + if (!result) { + s_logger.error("Failed to setup certificate for system vm: " + vm.getInstanceName()); + } + return; + } catch (final Exception e) { + s_logger.error("Retrying after catching exception while trying to secure agent for systemvm id=" + vm.getId(), e); + } + } + throw new CloudRuntimeException("Failed to setup and secure agent for systemvm id=" + vm.getId()); + } return; } else { if (s_logger.isDebugEnabled()) { diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java index b2d64393c111..38b505f561ac 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java @@ -47,7 +47,6 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR ExecutionResult result; try { result = getSystemVmVersionAndChecksum(serverResource, controlIp); - FileUtil.scpPatchFiles(controlIp, "/home/cloud", sshPort, pemFile, serverResource.newSrcFiles, LibvirtComputingResource.BASEPATH); } catch (CloudRuntimeException e) { return new PatchSystemVmAnswer(cmd, e.getMessage()); } @@ -59,7 +58,7 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR } String scriptChecksum = lines[1].trim(); - String checksum = serverResource.calculateCurrentChecksum(sysVMName).trim(); + String checksum = serverResource.calculateCurrentChecksum(sysVMName, "vms/cloud-scripts.tgz").trim(); if (!StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum)) { if (!cmd.isForced()) { @@ -71,6 +70,7 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR Pair patchResult = null; try { + FileUtil.scpPatchFiles(controlIp, "/home/cloud", sshPort, pemFile, serverResource.newSrcFiles, LibvirtComputingResource.BASEPATH); patchResult = SshHelper.sshExecute(controlIp, sshPort, "root", pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 600000); } catch (Exception e) { @@ -78,7 +78,17 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR } if (patchResult.first()) { - return new PatchSystemVmAnswer(cmd, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], lines[1]); + String scriptVersion = lines[1]; + if (patchResult.second() != null) { + String res = patchResult.second().replace("\n", " "); + String[] output = res.split(":"); + if (output.length != 2) { + s_logger.warn("Failed to get the latest script version"); + } else { + scriptVersion = output[1].split(" ")[0]; + } + } + return new PatchSystemVmAnswer(cmd, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], scriptVersion); } return new PatchSystemVmAnswer(cmd, patchResult.second()); } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java index 2ac8bf798482..b83514fd8f9c 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java @@ -121,6 +121,16 @@ public Answer execute(final StartCommand command, final LibvirtComputingResource try { File pemFile = new File(LibvirtComputingResource.SSHPRVKEYPATH); FileUtil.scpPatchFiles(controlIp, "/home/cloud", Integer.parseInt(LibvirtComputingResource.DEFAULTDOMRSSHPORT), pemFile, LibvirtComputingResource.newSrcFiles, LibvirtComputingResource.BASEPATH); +// if (Arrays.asList((new VirtualMachine.Type[]{VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm})).contains(vmSpec.getType())) { +//// for (String certFile : LibvirtComputingResource.certificateFiles) { +//// libvirtComputingResource.createFileInVR(controlIp, "/usr/local/cloud/systemvm/conf/", certFile, command.getCertificate()); +//// } +// if (VirtualMachine.Type.ConsoleProxy == vmSpec.getType() || VirtualMachine.Type.SecondaryStorageVm == vmSpec.getType()) { +// libvirtComputingResource. +// libvirtComputingResource.createFileInVR(controlIp, "/home/cloud", KeyStoreUtils.CACERT_FILENAME, command.getCaCertificates()); +// libvirtComputingResource.createFileInVR(controlIp, "/home/cloud", KeyStoreUtils.PKEY_FILENAME, command.getPrivateKey()); +// } +// } // TODO: May want to remove this when cert patching logic is moved Thread.sleep(10000); } catch (Exception e) { @@ -158,6 +168,28 @@ public Answer execute(final StartCommand command, final LibvirtComputingResource } } +// /** +// * Create temporary file and return its path +// */ +// private String createTemporaryFile(String certificateName, String certificate, String filePrefix) { +// String tempCerFilePath = String.format("/tmp/%s-%s", +// filePrefix, certificateName); +// s_logger.debug("Creating temporary certificate file into: " + tempCerFilePath); +// int result = Script.runSimpleBashScriptForExitValue(String.format("echo '%s' > %s", certificate, tempCerFilePath)); +// if (result != 0) { +// throw new CloudRuntimeException("Could not create the certificate file on path: " + tempCerFilePath); +// } +// return tempCerFilePath; +// } +// +// /** +// * Remove temporary file +// */ +// private void cleanupTemporaryFile(String temporaryFile) { +// s_logger.debug("Cleaning up temporary certificate file"); +// Script.runSimpleBashScript("rm -f " + temporaryFile); +// } + private void performAgentStartHook(String vmName, LibvirtComputingResource libvirtComputingResource) { try { LibvirtKvmAgentHook onStartHook = libvirtComputingResource.getStartHook(); diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index f759d118db17..f390c3d9300e 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -655,7 +655,7 @@ private ExecutionResult getSystemVmVersionAndChecksum(String controlIp) { } private Answer execute(PatchSystemVmCommand cmd) { - String controlIp = getRouterSshControlIp(cmd); + String controlIp = cmd.getAccessDetail((NetworkElementCommand.ROUTER_IP)); String sysVMName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); String homeDir = System.getProperty("user.home"); File pemFile = new File(homeDir + "/.ssh/id_rsa"); @@ -674,7 +674,7 @@ private Answer execute(PatchSystemVmCommand cmd) { } String scriptChecksum = lines[1].trim(); - String checksum = calculateCurrentChecksum(sysVMName).trim(); + String checksum = calculateCurrentChecksum(sysVMName, "vms/cloud-scripts.tgz").trim(); if (!org.apache.commons.lang3.StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum)) { if (!cmd.isForced()) { @@ -693,7 +693,17 @@ private Answer execute(PatchSystemVmCommand cmd) { } if (patchResult.first()) { - return new PatchSystemVmAnswer(cmd, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], lines[1]); + String scriptVersion = lines[1]; + if (patchResult.second() != null) { + String res = patchResult.second().replace("\n", " "); + String[] output = res.split(":"); + if (output.length != 2) { + s_logger.warn("Failed to get the latest script version"); + } else { + scriptVersion = output[1].split(" ")[0]; + } + } + return new PatchSystemVmAnswer(cmd, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], scriptVersion); } return new PatchSystemVmAnswer(cmd, patchResult.second()); diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java index 117ad3b1cdc7..1e9b0388883f 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java @@ -1124,9 +1124,6 @@ public VBD createPatchVbd(final Connection conn, final String vmName, final VM v _host.setSystemvmisouuid(vdi.getRecord(conn).uuid); } } - if (_host.getSystemvmisouuid() == null) { - throw new CloudRuntimeException("can not find systemvmiso"); - } } final VBD.Record cdromVBDR = new VBD.Record(); @@ -1136,10 +1133,8 @@ public VBD createPatchVbd(final Connection conn, final String vmName, final VM v cdromVBDR.userdevice = "3"; cdromVBDR.mode = Types.VbdMode.RO; cdromVBDR.type = Types.VbdType.CD; - final VBD cdromVBD = VBD.create(conn, cdromVBDR); - cdromVBD.insert(conn, VDI.getByUuid(conn, _host.getSystemvmisouuid())); - return cdromVBD; + return VBD.create(conn, cdromVBDR); } protected boolean createSecondaryStorageFolder(final Connection conn, final String remoteMountPath, final String newFolder, final String nfsVersion) { @@ -1428,7 +1423,7 @@ public VM createVmFromTemplate(final Connection conn, final VirtualMachineTO vmS final DiskTO[] disks = vmSpec.getDisks(); for (final DiskTO disk : disks) { if (disk.getType() == Volume.Type.ISO) { - final TemplateObjectTO iso = (TemplateObjectTO)disk.getData(); + final TemplateObjectTO iso = (TemplateObjectTO) disk.getData(); final String osType = iso.getGuestOsType(); if (osType != null) { final String isoGuestOsName = getGuestOsType(vmSpec.getPlatformEmulator()); diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixNetworkElementCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixNetworkElementCommandWrapper.java index da2bf1e126e2..3e763155fbdc 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixNetworkElementCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixNetworkElementCommandWrapper.java @@ -25,10 +25,11 @@ import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase; import com.cloud.resource.CommandWrapper; import com.cloud.resource.ResourceWrapper; +import org.apache.log4j.Logger; @ResourceWrapper(handles = NetworkElementCommand.class) public final class CitrixNetworkElementCommandWrapper extends CommandWrapper { - + private static final Logger s_logger = Logger.getLogger(CitrixNetworkElementCommandWrapper.class); @Override public Answer execute(final NetworkElementCommand command, final CitrixResourceBase citrixResourceBase) { final VirtualRoutingResource routingResource = citrixResourceBase.getVirtualRoutingResource(); diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java index 883c9378aa0c..e806e7e27d55 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java @@ -47,7 +47,6 @@ public Answer execute(PatchSystemVmCommand command, CitrixResourceBase serverRes ExecutionResult result; try { result = getSystemVmVersionAndChecksum(serverResource, controlIp); - serverResource.copyPatchFilesToVR(controlIp, "/home/cloud"); } catch (CloudRuntimeException e) { return new PatchSystemVmAnswer(command, e.getMessage()); } @@ -59,8 +58,7 @@ public Answer execute(PatchSystemVmCommand command, CitrixResourceBase serverRes } String scriptChecksum = lines[1].trim(); - String checksum = serverResource.calculateCurrentChecksum(sysVMName).trim(); - + String checksum = serverResource.calculateCurrentChecksum(sysVMName, "vms/cloud-scripts.tgz").trim(); if (!StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum)) { if (!command.isForced()) { String msg = String.format("No change in the scripts checksum, not patching systemVM %s", sysVMName); @@ -70,14 +68,23 @@ public Answer execute(PatchSystemVmCommand command, CitrixResourceBase serverRes } String patchResult = null; try { + serverResource.copyPatchFilesToVR(controlIp, "/home/cloud"); patchResult = serverResource.callHostPlugin(conn, "vmops", "runPatchScriptInDomr", "domrip", controlIp); } catch (Exception e) { return new PatchSystemVmAnswer(command, e.getMessage()); } - if (patchResult.startsWith("succ#")) { - return new PatchSystemVmAnswer(command, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], lines[1]); + String scriptVersion = lines[1]; + String res = patchResult.replace("\n", " "); + String[] output = res.split(":"); + if (output.length != 2) { + s_logger.warn("Failed to get the latest script version"); + } else { + scriptVersion = output[1].split(" ")[0]; + } + + return new PatchSystemVmAnswer(command, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], scriptVersion); } return new PatchSystemVmAnswer(command, patchResult.substring(5)); diff --git a/scripts/util/keystore-cert-import b/scripts/util/keystore-cert-import index 7c750a412eb8..cbfd0b40e855 100755 --- a/scripts/util/keystore-cert-import +++ b/scripts/util/keystore-cert-import @@ -18,15 +18,14 @@ PROPS_FILE="$1" KS_PASS="$2" -KS_VALIDITY="$3" -KS_FILE="$4" -MODE="$5" -CERT_FILE="$6" -CERT=$(echo "$7" | tr '^' '\n' | tr '~' ' ') -CACERT_FILE="$8" -CACERT=$(echo "$9" | tr '^' '\n' | tr '~' ' ') -PRIVKEY_FILE="${10}" -PRIVKEY=$(echo "${11}" | tr '^' '\n' | tr '~' ' ') +KS_FILE="$3" +MODE="$4" +CERT_FILE="$5" +CERT=$(echo "$6" | tr '^' '\n' | tr '~' ' ') +CACERT_FILE="$7" +CACERT=$(echo "$8" | tr '^' '\n' | tr '~' ' ') +PRIVKEY_FILE="$9" +PRIVKEY=$(echo "${10}" | tr '^' '\n' | tr '~' ' ') ALIAS="cloud" SYSTEM_FILE="/var/cache/cloud/cmdline" @@ -44,13 +43,14 @@ if [ ! -f "$LIBVIRTD_FILE" ]; then fi fi - if [ -f "$KS_FILE" ]; then - keytool -delete -noprompt -alias "$ALIAS" -keystore "$KS_FILE" -storepass "$KS_PASS" > /dev/null 2>&1 || true - fi - - CN=$(hostname --fqdn) - keytool -genkey -storepass "$KS_PASS" -keypass "$KS_PASS" -alias "$ALIAS" -keyalg RSA -validity "$KS_VALIDITY" -dname cn="$CN",ou="cloudstack",o="cloudstack",c="cloudstack" -keystore "$KS_FILE" > /dev/null 2>&1 +# if [ -f "$KS_FILE" ]; then +# keytool -delete -noprompt -alias "$ALIAS" -keystore "$KS_FILE" -storepass "$KS_PASS" > /dev/null 2>&1 || true +# fi +# +# CN=$(hostname --fqdn) +# keytool -genkey -storepass "$KS_PASS" -keypass "$KS_PASS" -alias "$ALIAS" -keyalg RSA -validity "$KS_VALIDITY" -dname cn="$CN",ou="cloudstack",o="cloudstack",c="cloudstack" -keystore "$KS_FILE" > /dev/null 2>&1 fi + # Find keystore password KS_PASS=$(sed -n '/keystore.passphrase/p' "$PROPS_FILE" 2>/dev/null | sed 's/keystore.passphrase=//g' 2>/dev/null) @@ -62,11 +62,17 @@ fi # Import certificate if [ ! -z "${CERT// }" ]; then echo "$CERT" > "$CERT_FILE" +elif [ ! -f "$CERT_FILE" ]; then + echo "Cannot find certificate file: $CERT_FILE, exiting" + exit fi # Import ca certs if [ ! -z "${CACERT// }" ]; then echo "$CACERT" > "$CACERT_FILE" +elif [ ! -f "$CACERT_FILE" ]; then + echo "Cannot find ca certificate file: $CACERT_FILE, exiting!" + exit fi # Import cacerts into the keystore @@ -77,9 +83,16 @@ for caChain in $(ls cloudca.*); do done rm -f cloudca.* +# Stop cloud service in systemvm +if [ "$MODE" == "ssh" ] && [ -f $SYSTEM_FILE ]; then + systemctl stop cloud > /dev/null 2>&1 +fi + # Import private key if available if [ ! -z "${PRIVKEY// }" ]; then echo "$PRIVKEY" > "$PRIVKEY_FILE" +fi +if [ -f "$PRIVKEY_FILE" ]; then # Re-initialize keystore when private key is provided keytool -delete -noprompt -alias "$ALIAS" -keystore "$KS_FILE" -storepass "$KS_PASS" 2>/dev/null || true openssl pkcs12 -export -name "$ALIAS" -in "$CERT_FILE" -inkey "$PRIVKEY_FILE" -out "$KS_FILE.p12" -password pass:"$KS_PASS" > /dev/null 2>&1 @@ -115,6 +128,10 @@ if [ -f "$SYSTEM_FILE" ]; then chmod 644 /usr/local/share/ca-certificates/cloudstack/ca.crt update-ca-certificates > /dev/null 2>&1 || true + # Ensure cloud service is running in systemvm + if [ "$MODE" == "ssh" ]; then + systemctl start cloud > /dev/null 2>&1 + fi fi # Fix file permission diff --git a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 40c6363ce169..15ab2cc44907 100644 --- a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -29,6 +29,7 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.utils.PasswordGenerator; import org.apache.cloudstack.agent.lb.IndirectAgentLB; import org.apache.cloudstack.ca.CAManager; import org.apache.cloudstack.context.CallContext; @@ -1283,8 +1284,8 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl if (dc.getDns2() != null) { buf.append(" dns2=").append(dc.getDns2()); } - - VirtualMachineGuru.appendCertificateDetails(buf, certificate); + buf.append(" keystore_password=").append(VirtualMachineGuru.getEncodedString(PasswordGenerator.generateRandomPassword(16))); +// VirtualMachineGuru.appendCertificateDetails(buf, certificate); String bootArgs = buf.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug("Boot Args for " + profile + ": " + bootArgs); diff --git a/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java b/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java index a67925bbef45..a33f61b98b74 100644 --- a/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java +++ b/server/src/main/java/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java @@ -186,14 +186,13 @@ private void setupAgentSecurity(final Connection sshConnection, final String age final SetupCertificateCommand certificateCommand = new SetupCertificateCommand(certificate); final SSHCmdHelper.SSHCmdResult setupCertResult = SSHCmdHelper.sshExecuteCmdWithResult(sshConnection, String.format("sudo /usr/share/cloudstack-common/scripts/util/%s " + - "/etc/cloudstack/agent/agent.properties %s %s " + - " /etc/cloudstack/agent/%s %s " + + "/etc/cloudstack/agent/agent.properties %s " + + "/etc/cloudstack/agent/%s %s " + "/etc/cloudstack/agent/%s \"%s\" " + "/etc/cloudstack/agent/%s \"%s\" " + "/etc/cloudstack/agent/%s \"%s\"", KeyStoreUtils.KS_IMPORT_SCRIPT, keystorePassword, - validityPeriod, KeyStoreUtils.KS_FILENAME, KeyStoreUtils.SSH_MODE, KeyStoreUtils.CERT_FILENAME, @@ -257,7 +256,6 @@ private void setupAgentSecurity(final Connection sshConnection, final String age } } - s_logger.info("PEARL - agent IP: "+ agentIp); sshConnection = new Connection(agentIp, 22); sshConnection.connect(null, 60000, 60000); diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index 03a806500de2..8a2dc90b8ccb 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -4717,6 +4717,7 @@ private boolean updateRouterDetails(Long routerId, String scriptVersion, String if (router == null) { throw new CloudRuntimeException(String.format("Failed to find router with id: %s", routerId)); } + router.setTemplateVersion(templateVersion); router.setScriptsVersion(scriptVersion); return routerDao.update(routerId, router); diff --git a/server/src/main/java/org/apache/cloudstack/ca/CAManagerImpl.java b/server/src/main/java/org/apache/cloudstack/ca/CAManagerImpl.java index 1e5d8127053b..5f4a16e1fe57 100644 --- a/server/src/main/java/org/apache/cloudstack/ca/CAManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/ca/CAManagerImpl.java @@ -39,6 +39,7 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; +import com.google.common.base.Strings; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.command.admin.ca.IssueCertificateCmd; @@ -184,11 +185,14 @@ public boolean provisionCertificate(final Host host, final Boolean reconnect, fi } CallContext.current().setEventDetails("host id: " + host.getId()); CallContext.current().putContextParameter(Host.class, host.getUuid()); - final String csr; + String csr = null; + try { - csr = generateKeyStoreAndCsr(host, null); - if (StringUtils.isEmpty(csr)) { - return false; + if (host.getType() != Host.Type.ConsoleProxy && host.getType() != Host.Type.SecondaryStorageVM) { + csr = generateKeyStoreAndCsr(host, null); + if (Strings.isNullOrEmpty(csr)) { + return false; + } } final Certificate certificate = issueCertificate(csr, Arrays.asList(host.getName(), host.getPrivateIpAddress()), Arrays.asList(host.getPrivateIpAddress(), host.getPublicIpAddress(), host.getStorageIpAddress()), CAManager.CertValidityPeriod.value(), caProvider); return deployCertificate(host, certificate, reconnect, null); @@ -209,6 +213,11 @@ public String generateKeyStoreAndCsr(final Host host, final Map return answer.getCsr(); } + private boolean isValidSystemVMType(Host.Type type) { + return Host.Type.SecondaryStorageVM.equals(type) || + Host.Type.ConsoleProxy.equals(type); + } + @Override public boolean deployCertificate(final Host host, final Certificate certificate, final Boolean reconnect, final Map sshAccessDetails) throws AgentUnavailableException, OperationTimedoutException { diff --git a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java index 8f6f12b07649..6c9ce8570551 100644 --- a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java +++ b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java @@ -32,7 +32,6 @@ import java.util.concurrent.Executor; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.ArrayUtils; import org.apache.log4j.xml.DOMConfigurator; import org.eclipse.jetty.websocket.api.Session; @@ -110,9 +109,10 @@ private static void configLog4j() { private static void configProxy(Properties conf) { s_logger.info("Configure console proxy..."); for (Object key : conf.keySet()) { - if (!ArrayUtils.contains(skipProperties, key)) { - s_logger.info("Property " + (String)key + ": " + conf.getProperty((String)key)); - } + s_logger.info("Property " + (String)key + ": " + conf.getProperty((String)key)); +// if (!ArrayUtils.contains(skipProperties, key)) { +// s_logger.info("Property " + (String)key + ": " + conf.getProperty((String)key)); +// } } String s = conf.getProperty("consoleproxy.httpListenPort"); @@ -251,9 +251,10 @@ public static void startWithContext(Properties conf, Object context, byte[] ksBi if (conf != null) { for (Object key : conf.keySet()) { - if (!ArrayUtils.contains(skipProperties, key)) { - s_logger.info("Context property " + (String) key + ": " + conf.getProperty((String) key)); - } +// if (!ArrayUtils.contains(skipProperties, key)) { + s_logger.info("Context property " + (String) key + ": " + conf.getProperty((String) key)); +// s_logger.info("Context property " + (String) key + ": " + conf.getProperty((String) key)); +// } } } diff --git a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java index fb300cbbeb93..f2db365d8dda 100644 --- a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java +++ b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java @@ -30,6 +30,7 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.utils.PasswordGenerator; import org.apache.cloudstack.agent.lb.IndirectAgentLB; import org.apache.cloudstack.ca.CAManager; import org.apache.cloudstack.context.CallContext; @@ -1164,8 +1165,8 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl } String nfsVersion = imageStoreDetailsUtil != null ? imageStoreDetailsUtil.getNfsVersion(secStore.getId()) : null; buf.append(" nfsVersion=").append(nfsVersion); - - VirtualMachineGuru.appendCertificateDetails(buf, certificate); + buf.append(" keystore_password=").append(VirtualMachineGuru.getEncodedString(PasswordGenerator.generateRandomPassword(16))); + //VirtualMachineGuru.appendCertificateDetails(buf, certificate); String bootArgs = buf.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug(String.format("Boot args for machine profile [%s]: [%s].", profile.toString(), bootArgs)); diff --git a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config index 15da63e93c6b..69044a3245b2 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config +++ b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config @@ -96,6 +96,9 @@ patch() { cleanup() { rm -rf /home/cloud/agent.zip mv /home/cloud/cloud-scripts.tgz /usr/share/cloud/cloud-scripts.tgz + if [ -f /home/cloud/cloud.crt ]; then + mv /home/cloud/cloud.crt /home/cloud/cloud.ca.crt /home/cloud/cloud.key /usr/local/cloud/systemvm/conf/ + fi } start() { diff --git a/systemvm/debian/opt/cloud/bin/setup/common.sh b/systemvm/debian/opt/cloud/bin/setup/common.sh index 3f4817a07795..82edc511e7fa 100755 --- a/systemvm/debian/opt/cloud/bin/setup/common.sh +++ b/systemvm/debian/opt/cloud/bin/setup/common.sh @@ -594,14 +594,10 @@ routing_svcs() { } setup_certificates() { - certificate=$(echo "$CERTIFICATE" | base64 -d) - cacertificate=$(echo "$CACERTIFICATE" | base64 -d) - privatekey=$(echo "$PRIVATEKEY" | base64 -d) kspass=$(echo "$KEYSTORE_PSSWD"| base64 -d) - ksvalidity="$KS_VALIDITY" - timeout 600 /opt/cloud/bin/keystore-cert-import /usr/local/cloud/systemvm/conf/agent.properties $kspass $ksvalidity \ - /usr/local/cloud/systemvm/conf/cloud.jks ssh /usr/local/cloud/systemvm/conf/cloud.crt \ - $certificate /usr/local/cloud/systemvm/conf/cloud.ca.crt $cacertificate /usr/local/cloud/systemvm/conf/cloud.key $privatekey + timeout 600 /opt/cloud/bin/keystore-cert-import /usr/local/cloud/systemvm/conf/agent.properties "$kspass" \ + /usr/local/cloud/systemvm/conf/cloud.jks ssh /usr/local/cloud/systemvm/conf/cloud.crt "" \ + /usr/local/cloud/systemvm/conf/cloud.ca.crt "" /usr/local/cloud/systemvm/conf/cloud.key "" } parse_cmd_line() { diff --git a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh index f8fcb51d94cb..82e020f3b353 100755 --- a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh +++ b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh @@ -37,10 +37,13 @@ setup_console_proxy() { enable_irqbalance 0 rm -f /etc/logrotate.d/cloud - setup_certificates - if [ $? -gt 0 ]; then - log_it "Failed to setup CA Certificate for $TYPE" - fi +# if [ -f /home/cloud/cloud.crt ]; then +# mv /home/cloud/cloud.crt /home/cloud/cloud.ca.crt /home/cloud/cloud.key /usr/local/cloud/systemvm/conf/ +# fi +# setup_certificates +# if [ $? -gt 0 ]; then +# log_it "Failed to setup CA Certificate for $TYPE" +# fi } setup_console_proxy diff --git a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh index 041853287a34..115521d17b2a 100755 --- a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh +++ b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh @@ -66,10 +66,10 @@ CORS setup_ntp rm -f /etc/logrotate.d/cloud - setup_certificates - if [ $? -gt 0 ]; then - log_it "Failed to setup CA Certificate for $TYPE" - fi +# setup_certificates +# if [ $? -gt 0 ]; then +# log_it "Failed to setup CA Certificate for $TYPE" +# fi } setup_secstorage diff --git a/systemvm/patch-sysvms.sh b/systemvm/patch-sysvms.sh index ee3c78a6270a..4edb780310ab 100644 --- a/systemvm/patch-sysvms.sh +++ b/systemvm/patch-sysvms.sh @@ -25,35 +25,38 @@ md5file=/var/cache/cloud/cloud-scripts-signature svcfile=/var/cache/cloud/enabled_svcs TYPE=$(grep -Po 'type=\K[a-zA-Z]*' $CMDLINE) patchfailed=0 - +backuprestored=0 backup_old_package() { mkdir -p $backupfolder - echo "Backing up keystore file and certificates" > $logfile + echo "Backing up keystore file and certificates" > $logfile 2>&1 mkdir -p $backupfolder/conf cp -r /usr/local/cloud/systemvm/conf/* $backupfolder/conf - echo "Backing up agent package" >> $logfile - zip -r $backupfolder/agent.zip /usr/local/cloud/systemvm/* >> $logfile 2>&1 + echo "Backing up agent package" >> $logfile 2>&1 + cd /usr/local/cloud/systemvm/ + zip -r $backupfolder/agent.zip * >> $logfile 2>&1 2>&1 + cd - cp $md5file $backupfolder - echo "Backing up cloud-scripts file" >> $logfile + echo "Backing up cloud-scripts file" >> $logfile 2>&1 tar -zcvf $backupfolder/cloud-scripts.tgz /etc/ /var/ /opt/ /root/ >> $logfile 2>&1 } restore_backup() { - echo "Restoring cloud scripts" >> $logfile + echo "Restoring cloud scripts" >> $logfile 2>&1 tar -xvf $backupfolder/cloud-scripts.tar -C / >> $logfile 2>&1 - echo "Restoring agent package" >> $logfile + echo "Restoring agent package" >> $logfile 2>&1 unzip $backupfolder/agent.zip -d /usr/local/cloud/systemvm/ >> $logfile 2>&1 - echo "Restore keystore file and certificates" + echo "Restore keystore file and certificates" >> $logfile 2>&1 mkdir -p "/usr/local/cloud/systemvm/conf/" cp -r $backupfolder/conf/* /usr/local/cloud/systemvm/conf/ + backuprestored=1 restart_services cp $backupfolder/cloud-scripts-signature $md5file } update_checksum() { newmd5=$(md5sum $1 | awk '{print $1}') - echo "checksum: " ${newmd5} >> $logfile + echo "checksum: " ${newmd5} >> $logfile 2>&1 echo ${newmd5} > ${md5file} } @@ -61,20 +64,24 @@ restart_services() { systemctl daemon-reload while IFS= read -r line do - echo "$line" for svc in ${line}; do - systemctl restart "$svc" - sleep 5 systemctl is-active --quiet "$svc" - if [ $? -gt 0 ]; then - echo "Failed to start "$svc" service. Patch Failed. Retrying again" >> $logfile - restore_backup - patchfailed=1 - break + if [ $? -eq 0 ]; then + systemctl restart "$svc" + sleep 5 + systemctl is-active --quiet "$svc" + if [ $? -gt 0 ]; then + echo "Failed to start "$svc" service. Patch Failed. Retrying again" >> $logfile 2>&1 + if [ $backuprestored == 0 ]; then + restore_backup + fi + patchfailed=1 + break + fi fi done if [ $patchfailed == 1 ]; then - break + return fi done < "$svcfile" } @@ -91,12 +98,12 @@ patch_systemvm() { echo "All" | unzip $newpath/agent.zip -d /usr/local/cloud/systemvm >> $logfile 2>&1 find /usr/local/cloud/systemvm/ -name \*.sh | xargs chmod 555 - echo "Extracting cloud scripts" >> $logfile + echo "Extracting cloud scripts" >> $logfile 2>&1 tar -xvf $newpath/cloud-scripts.tgz -C / >> $logfile 2>&1 if [ -f $backupfolder/conf/cloud.jks ]; then cp -r $backupfolder/conf/* /usr/local/cloud/systemvm/conf/ - echo "Restored keystore file and certs using backup" >> $logfile + echo "Restored keystore file and certs using backup" >> $logfile 2>&1 fi update_checksum $newpath/cloud-scripts.tgz @@ -111,4 +118,8 @@ backup_old_package patch_systemvm cleanup_systemVM +if [ $patchfailed == 0 ]; then + echo "version:$(cat ${md5file}) " +fi + exit $patchfailed diff --git a/utils/src/main/java/org/apache/cloudstack/utils/security/KeyStoreUtils.java b/utils/src/main/java/org/apache/cloudstack/utils/security/KeyStoreUtils.java index c6f8d21918c4..e78d14adbb2d 100644 --- a/utils/src/main/java/org/apache/cloudstack/utils/security/KeyStoreUtils.java +++ b/utils/src/main/java/org/apache/cloudstack/utils/security/KeyStoreUtils.java @@ -26,6 +26,7 @@ public class KeyStoreUtils { public static final String KS_SETUP_SCRIPT = "keystore-setup"; public static final String KS_IMPORT_SCRIPT = "keystore-cert-import"; + public static final String KS_SYSTEMVM_IMPORT_SCRIPT = "keystore-cert-import-sysvm"; public static final String AGENT_PROPSFILE = "agent.properties"; public static final String KS_PASSPHRASE_PROPERTY = "keystore.passphrase"; From e678b46d8a4d07ba23dc266a233018bb51fe5f13 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Fri, 7 Jan 2022 17:36:44 +0530 Subject: [PATCH 38/68] remove commented code + change core user to cloud for cks nodes --- debian/rules | 1 - engine/schema/pom.xml | 2 + packaging/centos7/cloud.spec | 3 - packaging/centos8/cloud.spec | 3 - packaging/suse15/cloud.spec | 3 - .../wrapper/LibvirtStartCommandWrapper.java | 10 ---- .../vmware/resource/VmwareResource.java | 21 +++---- .../KubernetesClusterActionWorker.java | 2 +- ...esClusterResourceModifierActionWorker.java | 2 +- .../resources/conf/k8s-control-node-add.yml | 10 ++-- .../main/resources/conf/k8s-control-node.yml | 10 ++-- .../src/main/resources/conf/k8s-node.yml | 10 ++-- scripts/vm/hypervisor/xenserver/xcposs/patch | 1 - .../vm/hypervisor/xenserver/xcpserver/patch | 1 - .../vm/hypervisor/xenserver/xenserver56/patch | 1 - .../hypervisor/xenserver/xenserver56fp1/patch | 1 - .../vm/hypervisor/xenserver/xenserver60/patch | 1 - .../vm/hypervisor/xenserver/xenserver62/patch | 1 - .../vm/hypervisor/xenserver/xenserver65/patch | 1 - .../debian/opt/cloud/bin/setup/cksnode.sh | 6 +- .../opt/cloud/bin/setup/cloud-early-config | 56 ++++++++++--------- systemvm/patch-sysvms.sh | 34 ++++++----- tools/appliance/build.sh | 4 +- .../scripts/configure_systemvm_services.sh | 8 ++- .../appliance/systemvmtemplate/template.json | 4 +- ui/public/locales/en.json | 2 +- 26 files changed, 94 insertions(+), 104 deletions(-) diff --git a/debian/rules b/debian/rules index 1e7f119f47e9..e216fc77a7e0 100755 --- a/debian/rules +++ b/debian/rules @@ -128,7 +128,6 @@ override_dh_auto_install: install -D client/target/utilities/bin/cloud-setup-management $(DESTDIR)/usr/bin/cloudstack-setup-management install -D client/target/utilities/bin/cloud-setup-encryption $(DESTDIR)/usr/bin/cloudstack-setup-encryption install -D client/target/utilities/bin/cloud-sysvmadm $(DESTDIR)/usr/bin/cloudstack-sysvmadm - #install -D systemvm/dist/systemvm.iso $(DESTDIR)/usr/share/$(PACKAGE)-common/vms/systemvm.iso install -D systemvm/dist/* $(DESTDIR)/usr/share/$(PACKAGE)-common/vms/ # We need jasypt for cloud-install-sys-tmplt, so this is a nasty hack to get it into the right place install -D agent/target/dependencies/jasypt-1.9.3.jar $(DESTDIR)/usr/share/$(PACKAGE)-common/lib diff --git a/engine/schema/pom.xml b/engine/schema/pom.xml index 165887e19aea..0d0bee1a2af5 100644 --- a/engine/schema/pom.xml +++ b/engine/schema/pom.xml @@ -102,8 +102,10 @@ File file = new File("./engine/schema/dist/systemvm-templates/md5sum.txt") def lines = file.readLines() for (template in templateList) { + println(template) def data = lines.findAll { it.contains(template) } if (data != null) { + println(template) def hypervisor = template.tokenize('-')[-1] pom.properties["$hypervisor" + ".checksum"] = data[0].tokenize(' ')[0] } diff --git a/packaging/centos7/cloud.spec b/packaging/centos7/cloud.spec index 96915a1660ab..81ee8a77a82f 100644 --- a/packaging/centos7/cloud.spec +++ b/packaging/centos7/cloud.spec @@ -231,7 +231,6 @@ mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms mkdir -p ${RPM_BUILD_ROOT}%{python_sitearch}/ mkdir -p ${RPM_BUILD_ROOT}/usr/bin cp -r scripts/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts -#install -D systemvm/dist/systemvm.iso ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/systemvm.iso install -D systemvm/dist/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/ install python/lib/cloud_utils.py ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py cp -r python/lib/cloudutils ${RPM_BUILD_ROOT}%{python_sitearch}/ @@ -601,8 +600,6 @@ pip3 install --upgrade urllib3 %dir %attr(0755,root,root) %{_datadir}/%{name}-common/vms %attr(0755,root,root) %{_datadir}/%{name}-common/scripts %attr(0755,root,root) /usr/bin/cloudstack-sccs -# TODO: Remove systemvm.iso -#%attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso %attr(0644, root, root) %{_datadir}/%{name}-common/vms/agent.zip %attr(0644, root, root) %{_datadir}/%{name}-common/vms/cloud-scripts.tgz %attr(0644, root, root) %{_datadir}/%{name}-common/vms/patch-sysvms.sh diff --git a/packaging/centos8/cloud.spec b/packaging/centos8/cloud.spec index 35e0e8d53578..1a946ba0dd95 100644 --- a/packaging/centos8/cloud.spec +++ b/packaging/centos8/cloud.spec @@ -224,7 +224,6 @@ mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms mkdir -p ${RPM_BUILD_ROOT}%{python_sitearch}/ mkdir -p ${RPM_BUILD_ROOT}/usr/bin cp -r scripts/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts -#install -D systemvm/dist/systemvm.iso ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/systemvm.iso install -D systemvm/dist/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/ install python/lib/cloud_utils.py ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py cp -r python/lib/cloudutils ${RPM_BUILD_ROOT}%{python_sitearch}/ @@ -589,8 +588,6 @@ pip install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz %dir %attr(0755,root,root) %{_datadir}/%{name}-common/vms %attr(0755,root,root) %{_datadir}/%{name}-common/scripts %attr(0755,root,root) /usr/bin/cloudstack-sccs -# TODO: Remove systemvm.iso -#%attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso %attr(0644, root, root) %{_datadir}/%{name}-common/vms/agent.zip %attr(0644, root, root) %{_datadir}/%{name}-common/vms/cloud-scripts.tgz %attr(0644, root, root) %{_datadir}/%{name}-common/vms/patch-sysvms.sh diff --git a/packaging/suse15/cloud.spec b/packaging/suse15/cloud.spec index bfdfa4826a1a..f355640c8650 100644 --- a/packaging/suse15/cloud.spec +++ b/packaging/suse15/cloud.spec @@ -226,7 +226,6 @@ mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms mkdir -p ${RPM_BUILD_ROOT}%{python_sitearch}/ mkdir -p ${RPM_BUILD_ROOT}/usr/bin cp -r scripts/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/scripts -#install -D systemvm/dist/systemvm.iso ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/systemvm.iso install -D systemvm/dist/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-common/vms/ install python/lib/cloud_utils.py ${RPM_BUILD_ROOT}%{python_sitearch}/cloud_utils.py cp -r python/lib/cloudutils ${RPM_BUILD_ROOT}%{python_sitearch}/ @@ -583,8 +582,6 @@ pip install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz %dir %attr(0755,root,root) %{_datadir}/%{name}-common/vms %attr(0755,root,root) %{_datadir}/%{name}-common/scripts %attr(0755,root,root) /usr/bin/cloudstack-sccs -# TODO: Remove systemvm.iso -#%attr(0644, root, root) %{_datadir}/%{name}-common/vms/systemvm.iso %attr(0644, root, root) %{_datadir}/%{name}-common/vms/agent.zip %attr(0644, root, root) %{_datadir}/%{name}-common/vms/cloud-scripts.tgz %attr(0644, root, root) %{_datadir}/%{name}-common/vms/patch-sysvms.sh diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java index b83514fd8f9c..1f6a0256cc83 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java @@ -121,16 +121,6 @@ public Answer execute(final StartCommand command, final LibvirtComputingResource try { File pemFile = new File(LibvirtComputingResource.SSHPRVKEYPATH); FileUtil.scpPatchFiles(controlIp, "/home/cloud", Integer.parseInt(LibvirtComputingResource.DEFAULTDOMRSSHPORT), pemFile, LibvirtComputingResource.newSrcFiles, LibvirtComputingResource.BASEPATH); -// if (Arrays.asList((new VirtualMachine.Type[]{VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm})).contains(vmSpec.getType())) { -//// for (String certFile : LibvirtComputingResource.certificateFiles) { -//// libvirtComputingResource.createFileInVR(controlIp, "/usr/local/cloud/systemvm/conf/", certFile, command.getCertificate()); -//// } -// if (VirtualMachine.Type.ConsoleProxy == vmSpec.getType() || VirtualMachine.Type.SecondaryStorageVm == vmSpec.getType()) { -// libvirtComputingResource. -// libvirtComputingResource.createFileInVR(controlIp, "/home/cloud", KeyStoreUtils.CACERT_FILENAME, command.getCaCertificates()); -// libvirtComputingResource.createFileInVR(controlIp, "/home/cloud", KeyStoreUtils.PKEY_FILENAME, command.getPrivateKey()); -// } -// } // TODO: May want to remove this when cert patching logic is moved Thread.sleep(10000); } catch (Exception e) { diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index f390c3d9300e..476734284749 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -692,17 +692,18 @@ private Answer execute(PatchSystemVmCommand cmd) { return new PatchSystemVmAnswer(cmd, e.getMessage()); } - if (patchResult.first()) { - String scriptVersion = lines[1]; - if (patchResult.second() != null) { - String res = patchResult.second().replace("\n", " "); - String[] output = res.split(":"); - if (output.length != 2) { - s_logger.warn("Failed to get the latest script version"); - } else { - scriptVersion = output[1].split(" ")[0]; - } + String scriptVersion = lines[1]; + if (patchResult.second() != null) { + String res = patchResult.second().replace("\n", " "); + String[] output = res.split(":"); + if (output.length != 2) { + s_logger.warn("Failed to get the latest script version"); + } else { + scriptVersion = output[1].split(" ")[0]; } + + } + if (patchResult.first()) { return new PatchSystemVmAnswer(cmd, String.format("Successfully patched systemVM %s ", sysVMName), lines[0], scriptVersion); } return new PatchSystemVmAnswer(cmd, patchResult.second()); diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java index 2399981c5764..eaf00f30a80e 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java @@ -84,7 +84,7 @@ public class KubernetesClusterActionWorker { - public static final String CLUSTER_NODE_VM_USER = "core"; + public static final String CLUSTER_NODE_VM_USER = "cloud"; public static final int CLUSTER_API_PORT = 6443; public static final int CLUSTER_NODES_DEFAULT_START_SSH_PORT = 2222; diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java index 20be84dda448..8a6c81e23ee1 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java @@ -189,7 +189,7 @@ private String getKubernetesNodeConfig(final String joinIp, final boolean ejectI // optional or conditionally applied String dockerConfigString = "write_files:\n" + " - path: /.docker/config.json\n" + - " owner: core:core\n" + + " owner: cloud:cloud\n" + " permissions: '0644'\n" + " content: |\n" + " {\n" + diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml index 87c592426a96..1699ffdcdc51 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml @@ -18,7 +18,7 @@ --- users: - - name: core + - name: cloud sudo: ALL=(ALL) NOPASSWD:ALL shell: /bin/bash ssh_authorized_keys: @@ -31,7 +31,7 @@ write_files: content: | #!/bin/bash -e - if [[ -f "/home/core/success" ]]; then + if [[ -f "/home/cloud/success" ]]; then echo "Already provisioned!" exit 0 fi @@ -192,7 +192,7 @@ write_files: content: | #!/bin/bash -e - if [[ -f "/home/core/success" ]]; then + if [[ -f "/home/cloud/success" ]]; then echo "Already provisioned!" exit 0 fi @@ -210,8 +210,8 @@ write_files: fi kubeadm join {{ k8s_control_node.join_ip }}:6443 --token {{ k8s_control_node.cluster.token }} --control-plane --certificate-key {{ k8s_control_node.cluster.ha.certificate.key }} --discovery-token-unsafe-skip-ca-verification - sudo touch /home/core/success - echo "true" > /home/core/success + sudo touch /home/cloud/success + echo "true" > /home/cloud/success - path: /etc/systemd/system/setup-kube-system.service permissions: '0755' diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml index 55daf7f6b7d3..c93167467b1f 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml @@ -18,7 +18,7 @@ --- users: - - name: core + - name: cloud sudo: ALL=(ALL) NOPASSWD:ALL shell: /bin/bash ssh_authorized_keys: @@ -51,7 +51,7 @@ write_files: content: | #!/bin/bash -e - if [[ -f "/home/core/success" ]]; then + if [[ -f "/home/cloud/success" ]]; then echo "Already provisioned!" exit 0 fi @@ -231,7 +231,7 @@ write_files: content: | #!/bin/bash -e - if [[ -f "/home/core/success" ]]; then + if [[ -f "/home/cloud/success" ]]; then echo "Already provisioned!" exit 0 fi @@ -267,8 +267,8 @@ write_files: /opt/bin/kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=admin || true /opt/bin/kubectl create clusterrolebinding kubernetes-dashboard-ui --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:kubernetes-dashboard || true - sudo touch /home/core/success - echo "true" > /home/core/success + sudo touch /home/cloud/success + echo "true" > /home/cloud/success - path: /etc/systemd/system/setup-kube-system.service permissions: '0755' diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml index ac05c6098f1a..3b22f801f3c3 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml @@ -18,7 +18,7 @@ --- users: - - name: core + - name: cloud sudo: ALL=(ALL) NOPASSWD:ALL shell: /bin/bash ssh_authorized_keys: @@ -31,7 +31,7 @@ write_files: content: | #!/bin/bash -e - if [[ -f "/home/core/success" ]]; then + if [[ -f "/home/cloud/success" ]]; then echo "Already provisioned!" exit 0 fi @@ -192,7 +192,7 @@ write_files: content: | #!/bin/bash -e - if [[ -f "/home/core/success" ]]; then + if [[ -f "/home/cloud/success" ]]; then echo "Already provisioned!" exit 0 fi @@ -210,8 +210,8 @@ write_files: fi kubeadm join {{ k8s_control_node.join_ip }}:6443 --token {{ k8s_control_node.cluster.token }} --discovery-token-unsafe-skip-ca-verification - sudo touch /home/core/success - echo "true" > /home/core/success + sudo touch /home/cloud/success + echo "true" > /home/cloud/success - path: /etc/systemd/system/setup-kube-system.service permissions: '0755' diff --git a/scripts/vm/hypervisor/xenserver/xcposs/patch b/scripts/vm/hypervisor/xenserver/xcposs/patch index 4686e67fe0a7..1edd35ad628a 100644 --- a/scripts/vm/hypervisor/xenserver/xcposs/patch +++ b/scripts/vm/hypervisor/xenserver/xcposs/patch @@ -31,7 +31,6 @@ vmops=..,0755,/usr/lib/xcp/plugins ovsgre=..,0755,/usr/lib/xcp/plugins ovstunnel=..,0755,/usr/lib/xcp/plugins vmopsSnapshot=..,0755,/usr/lib/xcp/plugins -#systemvm.iso=../../../../../vms,0644,/usr/share/xcp/packages/iso/ agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xcpserver/patch b/scripts/vm/hypervisor/xenserver/xcpserver/patch index da6ce60b7f68..8bb1eadd7034 100644 --- a/scripts/vm/hypervisor/xenserver/xcpserver/patch +++ b/scripts/vm/hypervisor/xenserver/xcpserver/patch @@ -31,7 +31,6 @@ NFSSR.py=/opt/xensource/sm vmops=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins -#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xenserver56/patch b/scripts/vm/hypervisor/xenserver/xenserver56/patch index fd844b4b6b05..16b1ce71b922 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver56/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver56/patch @@ -30,7 +30,6 @@ NFSSR.py=/opt/xensource/sm vmops=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins -#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch b/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch index 2a0f4b8aac78..bb09d255601e 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch @@ -30,7 +30,6 @@ NFSSR.py=/opt/xensource/sm vmops=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins -#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xenserver60/patch b/scripts/vm/hypervisor/xenserver/xenserver60/patch index e32be41affa6..2652c30cd05e 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver60/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver60/patch @@ -34,7 +34,6 @@ cloudstack_plugins.conf=..,0644,/etc/xensource cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins -#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xenserver62/patch b/scripts/vm/hypervisor/xenserver/xenserver62/patch index 9bf9b9bdac23..f18a325f05bf 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver62/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver62/patch @@ -35,7 +35,6 @@ cloudstack_plugins.conf=..,0644,/etc/xensource cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins cloud-plugin-storage=..,0755,/etc/xapi.d/plugins -#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/scripts/vm/hypervisor/xenserver/xenserver65/patch b/scripts/vm/hypervisor/xenserver/xenserver65/patch index 9bf9b9bdac23..f18a325f05bf 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver65/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver65/patch @@ -35,7 +35,6 @@ cloudstack_plugins.conf=..,0644,/etc/xensource cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins cloud-plugin-storage=..,0755,/etc/xapi.d/plugins -#systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso agent.zip=../../../../../vms,0644,/opt/xensource/packages/resources/ cloud-scripts.tgz=../../../../../vms,0644,/opt/xensource/packages/resources/ patch-sysvms.sh=../../../../../vms,0644,/opt/xensource/packages/resources/ diff --git a/systemvm/debian/opt/cloud/bin/setup/cksnode.sh b/systemvm/debian/opt/cloud/bin/setup/cksnode.sh index 7f580ace9cd4..78ae96631ad9 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cksnode.sh +++ b/systemvm/debian/opt/cloud/bin/setup/cksnode.sh @@ -31,8 +31,8 @@ setup_k8s_node() { systemctl restart ssh # Prevent root login - > /root/.ssh/authorized_keys - passwd -l root +# > /root/.ssh/authorized_keys +# passwd -l root #sed -i 's#root:x:0:0:root:/root:/bin/bash#root:x:0:0:root:/root:/sbin/nologin#' /etc/passwd # Update containerd configuration @@ -66,7 +66,7 @@ setup_k8s_node() { log_it "Starting cloud-init services" systemctl enable --now --no-block containerd - if [ -f /home/core/success ]; then + if [ -f /home/cloud/success ]; then systemctl stop cloud-init cloud-config cloud-final systemctl disable cloud-init cloud-config cloud-final else diff --git a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config index 69044a3245b2..13fa9987a5e7 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config +++ b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config @@ -59,38 +59,42 @@ patch() { return 0 fi + CMDLINE=/var/cache/cloud/cmdline + export TYPE=$(grep -Po 'type=\K[a-zA-Z]*' $CMDLINE) retry=60 local patched=false - while [ $retry -gt 0 ] - do - if [ -f $patchfile ]; then - eval $(validate_checksums $md5file $patchfile) - if [ "$oldmd5" != "$newmd5" ] && [ -f ${patchfile} ] && [ "$newmd5" != "" ] - then - tar xzf $patchfile -C / - ls -lrt /opt/cloud/bin/keystore* - echo ${newmd5} > ${md5file} - log_it "Patched scripts using $patchfile" - touch /var/cache/cloud/patch.required + if [ "$TYPE" != "cksnode" ]; then + while [ $retry -gt 0 ] + do + if [ -f $patchfile ]; then + eval $(validate_checksums $md5file $patchfile) + if [ "$oldmd5" != "$newmd5" ] && [ -f ${patchfile} ] && [ "$newmd5" != "" ] + then + tar xzf $patchfile -C / + ls -lrt /opt/cloud/bin/keystore* + echo ${newmd5} > ${md5file} + log_it "Patched scripts using $patchfile" + touch /var/cache/cloud/patch.required + fi + + if [ -f $privkey ]; then + cp -f $privkey /root/.ssh/ + chmod go-rwx /root/.ssh/authorized_keys + fi + patched=true + break fi - if [ -f $privkey ]; then - cp -f $privkey /root/.ssh/ - chmod go-rwx /root/.ssh/authorized_keys - fi - patched=true - break - fi - - sleep 2 - retry=$(($retry-1)) - log_it "Could not find patch file, retrying" - done + sleep 2 + retry=$(($retry-1)) + log_it "Could not find patch file, retrying" + done - if [ $retry -eq 0 ] && [ "$patched" == "false" ]; then - return 2 + if [ $retry -eq 0 ] && [ "$patched" == "false" ]; then + return 2 + fi + return 0 fi - return 0 } cleanup() { diff --git a/systemvm/patch-sysvms.sh b/systemvm/patch-sysvms.sh index 4edb780310ab..148c8a80b9da 100644 --- a/systemvm/patch-sysvms.sh +++ b/systemvm/patch-sysvms.sh @@ -29,13 +29,17 @@ backuprestored=0 backup_old_package() { mkdir -p $backupfolder - echo "Backing up keystore file and certificates" > $logfile 2>&1 - mkdir -p $backupfolder/conf - cp -r /usr/local/cloud/systemvm/conf/* $backupfolder/conf - echo "Backing up agent package" >> $logfile 2>&1 - cd /usr/local/cloud/systemvm/ - zip -r $backupfolder/agent.zip * >> $logfile 2>&1 2>&1 - cd - + if [ -d /usr/local/cloud/systemvm/conf/ ]; then + echo "Backing up keystore file and certificates" > $logfile 2>&1 + mkdir -p $backupfolder/conf + cp -r /usr/local/cloud/systemvm/conf/* $backupfolder/conf + fi + if [ -d /usr/local/cloud/systemvm/ ]; then + echo "Backing up agent package" >> $logfile 2>&1 + cd /usr/local/cloud/systemvm/ + zip -r $backupfolder/agent.zip * >> $logfile 2>&1 2>&1 + cd - + fi cp $md5file $backupfolder echo "Backing up cloud-scripts file" >> $logfile 2>&1 tar -zcvf $backupfolder/cloud-scripts.tgz /etc/ /var/ /opt/ /root/ >> $logfile 2>&1 @@ -45,10 +49,12 @@ restore_backup() { echo "Restoring cloud scripts" >> $logfile 2>&1 tar -xvf $backupfolder/cloud-scripts.tar -C / >> $logfile 2>&1 echo "Restoring agent package" >> $logfile 2>&1 - unzip $backupfolder/agent.zip -d /usr/local/cloud/systemvm/ >> $logfile 2>&1 - echo "Restore keystore file and certificates" >> $logfile 2>&1 - mkdir -p "/usr/local/cloud/systemvm/conf/" - cp -r $backupfolder/conf/* /usr/local/cloud/systemvm/conf/ + if [ -f $backupfolder/agent.zip ]; then + unzip $backupfolder/agent.zip -d /usr/local/cloud/systemvm/ >> $logfile 2>&1 + echo "Restore keystore file and certificates" >> $logfile 2>&1 + mkdir -p "/usr/local/cloud/systemvm/conf/" + cp -r $backupfolder/conf/* /usr/local/cloud/systemvm/conf/ + fi backuprestored=1 restart_services cp $backupfolder/cloud-scripts-signature $md5file @@ -95,9 +101,11 @@ cleanup_systemVM() { patch_systemvm() { rm -rf /usr/local/cloud/systemvm mkdir -p /usr/local/cloud/systemvm - echo "All" | unzip $newpath/agent.zip -d /usr/local/cloud/systemvm >> $logfile 2>&1 - find /usr/local/cloud/systemvm/ -name \*.sh | xargs chmod 555 + if [ "$TYPE" == "consoleproxy" ] || [ "$TYPE" == "secstorage" ]; then + echo "All" | unzip $newpath/agent.zip -d /usr/local/cloud/systemvm >> $logfile 2>&1 + find /usr/local/cloud/systemvm/ -name \*.sh | xargs chmod 555 + fi echo "Extracting cloud scripts" >> $logfile 2>&1 tar -xvf $newpath/cloud-scripts.tgz -C / >> $logfile 2>&1 diff --git a/tools/appliance/build.sh b/tools/appliance/build.sh index 5a97c9dbf6b6..285d818c0c75 100755 --- a/tools/appliance/build.sh +++ b/tools/appliance/build.sh @@ -348,9 +348,9 @@ function main() { packer_build # process the disk at dist - kvm_export +# kvm_export # ovm_export - xen_server_export +# xen_server_export vmware_export # hyperv_export rm -f "dist/${appliance}" diff --git a/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh b/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh index 4f97b1b5505e..36b324a314f8 100644 --- a/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh +++ b/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh @@ -50,9 +50,11 @@ function configure_cacerts() { CDIR=$(pwd) cd /tmp # Add LetsEncrypt ca-cert - wget https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.der - keytool -trustcacerts -keystore /etc/ssl/certs/java/cacerts -storepass changeit -noprompt -importcert -alias letsencryptauthorityx3cross -file lets-encrypt-x3-cross-signed.der - rm -f lets-encrypt-x3-cross-signed.der + wget https://letsencrypt.org/certs/lets-encrypt-r3.der + wget https://letsencrypt.org/certs/isrgrootx1.der + keytool -trustcacerts -keystore /etc/ssl/certs/java/cacerts -storepass changeit -noprompt -importcert -alias letsencryptauthorityr3 -file lets-encrypt-r3.der + keytool -trustcacerts -keystore /etc/ssl/certs/java/cacerts -storepass changeit -noprompt -importcert -alias letsencryptauthorityx1 -file isrgrootx1.der + rm -f lets-encrypt-r3.der isrgrootx1.der cd $CDIR } diff --git a/tools/appliance/systemvmtemplate/template.json b/tools/appliance/systemvmtemplate/template.json index 46fdbc90a750..31eb2ea5abf1 100644 --- a/tools/appliance/systemvmtemplate/template.json +++ b/tools/appliance/systemvmtemplate/template.json @@ -27,8 +27,8 @@ "format": "qcow2", "headless": true, "http_directory": "http", - "iso_checksum": "sha512:02257c3ec27e45d9f022c181a69b59da67e5c72871cdb4f9a69db323a1fad58093f2e69702d29aa98f5f65e920e0b970d816475a5a936e1f3bf33832257b7e92", - "iso_url": "https://cdimage.debian.org/debian-cd/11.1.0/amd64/iso-cd/debian-11.1.0-amd64-netinst.iso", + "iso_checksum": "sha512:c685b85cf9f248633ba3cd2b9f9e781fa03225587e0c332aef2063f6877a1f0622f56d44cf0690087b0ca36883147ecb5593e3da6f965968402cdbdf12f6dd74", + "iso_url": "https://cdimage.debian.org/debian-cd/11.2.0/amd64/iso-cd/debian-11.2.0-amd64-netinst.iso", "net_device": "virtio-net", "output_directory": "../dist", "qemuargs": [ diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index d81dd7a1e3ec..76e2f35ced56 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -1241,7 +1241,7 @@ "label.keypair": "SSH Key Pair", "label.kubeconfig.cluster": "Kubernetes Cluster Config", "label.kubernetes": "Kubernetes", -"label.kubernetes.access.details": "The kubernetes nodes can be accessed via ssh using:
ssh -i [ssh_key] -p [port_number] core@[public_ip_address]

where,
ssh_key: points to the ssh private key file corresponding to the key that was associated while creating the Kubernetes cluster. If no ssh key was provided during Kubernetes cluster creation, use the ssh private key of the management server.
port_number: can be obtained from the Port Forwarding Tab (Public Port column)", +"label.kubernetes.access.details": "The kubernetes nodes can be accessed via ssh using:
ssh -i [ssh_key] -p [port_number] cloud@[public_ip_address]

where,
ssh_key: points to the ssh private key file corresponding to the key that was associated while creating the Kubernetes cluster. If no ssh key was provided during Kubernetes cluster creation, use the ssh private key of the management server.
port_number: can be obtained from the Port Forwarding Tab (Public Port column)", "label.kubernetes.cluster": "Kubernetes cluster", "label.kubernetes.cluster.create": "Create Kubernetes Cluster", "label.kubernetes.cluster.delete": "Delete Kubernetes Cluster", From 0293ab741192e860ad7eebfc1d5aa11f32087452 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Fri, 7 Jan 2022 17:57:12 +0530 Subject: [PATCH 39/68] Update ownership of ssh directory --- .../src/main/resources/conf/k8s-control-node-add.yml | 1 + .../src/main/resources/conf/k8s-control-node.yml | 1 + .../kubernetes-service/src/main/resources/conf/k8s-node.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml index 1699ffdcdc51..db295188eba5 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml @@ -241,6 +241,7 @@ write_files: ExecStart=/opt/bin/deploy-kube-system runcmd: + - chown -R cloud:cloud /home/cloud/.ssh - [ systemctl, start, setup-kube-system ] - [ systemctl, start, deploy-kube-system ] diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml index c93167467b1f..730477bd4eef 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml @@ -298,6 +298,7 @@ write_files: ExecStart=/opt/bin/deploy-kube-system runcmd: + - chown -R cloud:cloud /home/cloud/.ssh - [ systemctl, start, setup-kube-system ] - [ systemctl, start, deploy-kube-system ] diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml index 3b22f801f3c3..eea369921ac8 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml @@ -241,5 +241,6 @@ write_files: ExecStart=/opt/bin/deploy-kube-system runcmd: + - chown -R cloud:cloud /home/cloud/.ssh - [ systemctl, start, setup-kube-system ] - [ systemctl, start, deploy-kube-system ] From f37d74f79101f1ccabad8bdd7654a9c16d06d9ae Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Mon, 10 Jan 2022 17:26:39 +0530 Subject: [PATCH 40/68] NEED TO DISCUSS - add on the fly template conversion as an ExecStartPre action (systemd) --- debian/control | 2 +- engine/schema/pom.xml | 57 +++---- packaging/centos7/cloud.spec | 1 + packaging/centos8/cloud.spec | 1 + packaging/suse15/cloud.spec | 1 + .../systemd/cloudstack-management.service | 2 + scripts/installer/export-templates.sh | 158 ++++++++++++++++++ scripts/util/keystore-cert-import | 5 +- systemvm/debian/opt/cloud/bin/setup/common.sh | 7 - .../opt/cloud/bin/setup/consoleproxy.sh | 7 - .../debian/opt/cloud/bin/setup/secstorage.sh | 4 - 11 files changed, 194 insertions(+), 51 deletions(-) create mode 100644 scripts/installer/export-templates.sh diff --git a/debian/control b/debian/control index 066994785b38..06edfa3c5cac 100644 --- a/debian/control +++ b/debian/control @@ -15,7 +15,7 @@ Description: A common package which contains files which are shared by several C Package: cloudstack-management Architecture: all -Depends: ${python3:Depends}, openjdk-11-jre-headless | java11-runtime-headless | java11-runtime | openjdk-11-jre-headless | zulu-11, cloudstack-common (= ${source:Version}), net-tools, sudo, python3-mysql.connector, augeas-tools, mysql-client | mariadb-client, adduser, bzip2, ipmitool, file, gawk, iproute2, qemu-utils, python3-dnspython, lsb-release, init-system-helpers (>= 1.14~), python3-setuptools +Depends: ${python3:Depends}, openjdk-11-jre-headless | java11-runtime-headless | java11-runtime | openjdk-11-jre-headless | zulu-11, cloudstack-common (= ${source:Version}), net-tools, sudo, python3-mysql.connector, augeas-tools, mysql-client | mariadb-client, adduser, bzip2, ipmitool, file, gawk, iproute2, qemu-utils, python3-dnspython, lsb-release, init-system-helpers (>= 1.14~), python3-setuptools, libguestfs-tools Conflicts: cloud-server, cloud-client, cloud-client-ui Description: CloudStack server library The CloudStack management server diff --git a/engine/schema/pom.xml b/engine/schema/pom.xml index 0d0bee1a2af5..1258289db98b 100644 --- a/engine/schema/pom.xml +++ b/engine/schema/pom.xml @@ -74,7 +74,6 @@ def projectVersion = project.properties['project.systemvm.template.version'] - println(projectVersion) String[] versionParts = projectVersion.tokenize('.') pom.properties['cs.version'] = versionParts[0] + "." + versionParts[1] pom.properties['patch.version'] = versionParts[2] @@ -90,9 +89,7 @@ def csVersion = pom.properties['cs.version'] - println(csVersion) def patch = pom.properties['patch.version'] - println(patch) def templateList = [] templateList.add("systemvmtemplate-${csVersion}.${patch}-kvm") templateList.add("systemvmtemplate-${csVersion}.${patch}-vmware") @@ -102,10 +99,8 @@ File file = new File("./engine/schema/dist/systemvm-templates/md5sum.txt") def lines = file.readLines() for (template in templateList) { - println(template) def data = lines.findAll { it.contains(template) } if (data != null) { - println(template) def hypervisor = template.tokenize('-')[-1] pom.properties["$hypervisor" + ".checksum"] = data[0].tokenize(' ')[0] } @@ -193,32 +188,32 @@ ${kvm.checksum} - - download-vmware-template - - wget - - - true - - http://10.0.3.122/systemvmtemplate/custom/cks-debian/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-vmware.ova - ${basedir}/dist/systemvm-templates/ - ${vmware.checksum} - - - - download-xenserver-template - - wget - - - true - - http://10.0.3.122/systemvmtemplate/custom/cks-debian/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-xen.vhd.bz2 - ${basedir}/dist/systemvm-templates/ - ${xen.checksum} - - + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packaging/centos7/cloud.spec b/packaging/centos7/cloud.spec index 81ee8a77a82f..b2f77c5a83b2 100644 --- a/packaging/centos7/cloud.spec +++ b/packaging/centos7/cloud.spec @@ -79,6 +79,7 @@ Requires: /sbin/service Requires: /sbin/chkconfig Requires: /usr/bin/ssh-keygen Requires: genisoimage +Requires: libguestfs-tools Requires: ipmitool Requires: %{name}-common = %{_ver} Requires: iptables-services diff --git a/packaging/centos8/cloud.spec b/packaging/centos8/cloud.spec index 1a946ba0dd95..6a3627a57771 100644 --- a/packaging/centos8/cloud.spec +++ b/packaging/centos8/cloud.spec @@ -74,6 +74,7 @@ Requires: /sbin/service Requires: /sbin/chkconfig Requires: /usr/bin/ssh-keygen Requires: genisoimage +Requires: libguestfs-tools Requires: ipmitool Requires: %{name}-common = %{_ver} Requires: iptables-services diff --git a/packaging/suse15/cloud.spec b/packaging/suse15/cloud.spec index f355640c8650..77b6f6e95ac4 100644 --- a/packaging/suse15/cloud.spec +++ b/packaging/suse15/cloud.spec @@ -75,6 +75,7 @@ Requires: /sbin/service Requires: /sbin/chkconfig Requires: /usr/bin/ssh-keygen Requires: mkisofs +Requires: libguestfs-tools Requires: ipmitool Requires: %{name}-common = %{_ver} Requires: qemu-tools diff --git a/packaging/systemd/cloudstack-management.service b/packaging/systemd/cloudstack-management.service index b979f7f375a7..aedd3a170ae4 100644 --- a/packaging/systemd/cloudstack-management.service +++ b/packaging/systemd/cloudstack-management.service @@ -34,7 +34,9 @@ User=cloud EnvironmentFile=/etc/default/cloudstack-management WorkingDirectory=/var/log/cloudstack/management PIDFile=/var/run/cloudstack-management.pid +ExecStartPre=/bin/bash /usr/share/cloudstack-management/templates/systemvm/export-templates.sh ExecStart=/usr/bin/java $JAVA_DEBUG $JAVA_OPTS -cp $CLASSPATH $BOOTSTRAP_CLASS +TimeoutSec=900 [Install] WantedBy=multi-user.target diff --git a/scripts/installer/export-templates.sh b/scripts/installer/export-templates.sh new file mode 100644 index 000000000000..578854df437a --- /dev/null +++ b/scripts/installer/export-templates.sh @@ -0,0 +1,158 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +METADATA_FILE="metadata.ini" +IMAGE_PATH=${1:-"/usr/share/cloudstack-management/templates/systemvm/"} +TEMPLATE_VERSION=$(awk -F "=" '/version/ {print $2}' ${IMAGE_PATH}${METADATA_FILE} | xargs) +TEMPLATE_PATH="/usr/share/cloudstack-management/templates/systemvm/" +VERSION="${TEMPLATE_VERSION%.*}" +PREFIX=${2:-"systemvmtemplate-$VERSION"} +TEMP_IMAGE_PATH="/tmp/sysvm_convert/" + +if [ -f ${IMAGE_PATH}${PREFIX}-kvm.qcow2.bxz2 ]; then + mkdir -p $TEMP_IMAGE_PATH + cp -r $IMAGE_PATH/* $TEMP_IMAGE_PATH + cd $TEMP_IMAGE_PATH + bzip2 -dc $PREFIX-kvm.qcow2.bz2 > $PREFIX-kvm.qcow2 + # Export for KVM + virt-sparsify $PREFIX-kvm.qcow2 --compress -o compat=0.10 $PREFIX-kvm-temp.qcow2 + + # Export for VMware + qemu-img convert -f qcow2 -O vmdk -o adapter_type=lsilogic,subformat=streamOptimized,compat6 $PREFIX-kvm-temp.qcow2 $PREFIX-vmware.vmdk + size=$(stat --printf="%s" $PREFIX-vmware.vmdk) + +cat < $PREFIX-vmware.ovf + + + + + + + + Virtual disk information + + + + A virtual machine + $PREFIX-vmware + + The kind of installed guest operating system + + + Virtual hardware requirements + + Virtual Hardware Family + 0 + $PREFIX-vmware + vmx-11 + + + hertz * 10^6 + Number of Virtual CPUs + 1 virtual CPU(s) + 1 + 3 + 1 + + + byte * 2^20 + Memory Size + 256MB of memory + 2 + 4 + 256 + + + 0 + SCSI Controller + scsiController0 + 3 + lsilogic + 6 + + + 0 + IDE Controller + ideController0 + 4 + 5 + + + 0 + false + cdrom0 + 5 + 4 + 15 + + + 0 + disk0 + ovf:/disk/vmdisk1 + 6 + 3 + 17 + + + false + video + 7 + 24 + + + + + + false + vmci + 8 + vmware.vmci + 1 + + + + + + + + A human-readable annotation + $PREFIX-vmware + + + +EOF +cat < $PREFIX-vmware.mf +SHA1($PREFIX-vmware.ovf)= $(sha1sum $PREFIX-vmware.ovf|awk '{print $1}') +SHA1($PREFIX-vmware.vmdk)= $(sha1sum $PREFIX-vmware.vmdk |awk '{print $1}') +EOF + + tar -cvf $PREFIX-vmware.ova $PREFIX-vmware.ovf $PREFIX-vmware.mf $PREFIX-vmware.vmdk + checksum=$(md5sum $PREFIX-vmware.ova | awk '{print $1}') + sed -i '/^\['"vmware"']/,/^\[/{s/^checksum[[:space:]]*=.*/checksum = '"$checksum"'/}' ./$METADATA_FILE + + # Export for XenServer/XCP-ng + qemu-img convert -f qcow2 -O vpc $PREFIX-kvm.qcow2 $PREFIX-xen.vhd + bzip2 $PREFIX-xen.vhd + checksum=$(md5sum $PREFIX-xen.vhd.bz2 | awk '{print $1}') + sed -i '/^\['"xenserver"']/,/^\[/{s/^checksum[[:space:]]*=.*/checksum = '"$checksum"'/}' $METADATA_FILE + + rm -rf $PREFIX-kvm*.qcow2 $PREFIX-xen.vhd *.mf *.ovf *.vmdk + sudo cp $TEMP_IMAGE_PATH/$PREFIX* $TEMP_IMAGE_PATH/metadata.ini $IMAGE_PATH + cd - + rm -rf $TEMP_IMAGE_PATH +fi \ No newline at end of file diff --git a/scripts/util/keystore-cert-import b/scripts/util/keystore-cert-import index cbfd0b40e855..0a112e9303e8 100755 --- a/scripts/util/keystore-cert-import +++ b/scripts/util/keystore-cert-import @@ -91,8 +91,11 @@ fi # Import private key if available if [ ! -z "${PRIVKEY// }" ]; then echo "$PRIVKEY" > "$PRIVKEY_FILE" +else + > "$PRIVKEY_FILE" fi -if [ -f "$PRIVKEY_FILE" ]; then + +if [ -f "$PRIVKEY_FILE" ] && [ -s "$PRIVKEY_FILE" ]; then # Re-initialize keystore when private key is provided keytool -delete -noprompt -alias "$ALIAS" -keystore "$KS_FILE" -storepass "$KS_PASS" 2>/dev/null || true openssl pkcs12 -export -name "$ALIAS" -in "$CERT_FILE" -inkey "$PRIVKEY_FILE" -out "$KS_FILE.p12" -password pass:"$KS_PASS" > /dev/null 2>&1 diff --git a/systemvm/debian/opt/cloud/bin/setup/common.sh b/systemvm/debian/opt/cloud/bin/setup/common.sh index 82edc511e7fa..cfaeb941715e 100755 --- a/systemvm/debian/opt/cloud/bin/setup/common.sh +++ b/systemvm/debian/opt/cloud/bin/setup/common.sh @@ -593,13 +593,6 @@ routing_svcs() { fi } -setup_certificates() { - kspass=$(echo "$KEYSTORE_PSSWD"| base64 -d) - timeout 600 /opt/cloud/bin/keystore-cert-import /usr/local/cloud/systemvm/conf/agent.properties "$kspass" \ - /usr/local/cloud/systemvm/conf/cloud.jks ssh /usr/local/cloud/systemvm/conf/cloud.crt "" \ - /usr/local/cloud/systemvm/conf/cloud.ca.crt "" /usr/local/cloud/systemvm/conf/cloud.key "" -} - parse_cmd_line() { CMDLINE=$(cat /var/cache/cloud/cmdline) TYPE="unknown" diff --git a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh index 82e020f3b353..8006f6bb2445 100755 --- a/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh +++ b/systemvm/debian/opt/cloud/bin/setup/consoleproxy.sh @@ -37,13 +37,6 @@ setup_console_proxy() { enable_irqbalance 0 rm -f /etc/logrotate.d/cloud -# if [ -f /home/cloud/cloud.crt ]; then -# mv /home/cloud/cloud.crt /home/cloud/cloud.ca.crt /home/cloud/cloud.key /usr/local/cloud/systemvm/conf/ -# fi -# setup_certificates -# if [ $? -gt 0 ]; then -# log_it "Failed to setup CA Certificate for $TYPE" -# fi } setup_console_proxy diff --git a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh index 115521d17b2a..3b21ed5cae17 100755 --- a/systemvm/debian/opt/cloud/bin/setup/secstorage.sh +++ b/systemvm/debian/opt/cloud/bin/setup/secstorage.sh @@ -66,10 +66,6 @@ CORS setup_ntp rm -f /etc/logrotate.d/cloud -# setup_certificates -# if [ $? -gt 0 ]; then -# log_it "Failed to setup CA Certificate for $TYPE" -# fi } setup_secstorage From ff7d4ed8699c9f3da24dc2eff591c3033e9ee20f Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Wed, 19 Jan 2022 11:37:05 +0530 Subject: [PATCH 41/68] Add UI changes + move changes from patch file to runcmd --- .../admin/systemvm/PatchSystemVMCmd.java | 2 +- .../user/network/RestartNetworkCmd.java | 2 +- .../cloud/resource/ServerResourceBase.java | 4 +- .../orchestration/NetworkOrchestrator.java | 4 ++ .../upgrade/SystemVmTemplateRegistration.java | 10 ++- .../cluster/KubernetesClusterManagerImpl.java | 30 +++----- ...esClusterResourceModifierActionWorker.java | 71 +++++++++---------- .../KubernetesClusterStartWorker.java | 2 + .../cluster/CreateKubernetesClusterCmd.java | 8 --- .../resources/conf/k8s-control-node-add.yml | 19 +++++ .../main/resources/conf/k8s-control-node.yml | 19 +++++ .../src/main/resources/conf/k8s-node.yml | 19 +++++ .../debian/opt/cloud/bin/setup/cksnode.sh | 9 +-- ui/public/locales/en.json | 4 ++ ui/src/config/section/image.js | 1 - ui/src/config/section/infra/systemVms.js | 12 ++++ .../views/compute/CreateKubernetesCluster.vue | 8 --- .../java/com/cloud/utils/EncryptionUtil.java | 16 ----- .../utils/security/DigestHelper.java | 19 +++++ 19 files changed, 154 insertions(+), 105 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java index 481e62cffb54..0f08ad7f0a20 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java @@ -47,7 +47,7 @@ public class PatchSystemVMCmd extends BaseAsyncCmd { private Long id; @Parameter(name = ApiConstants.FORCED, type = CommandType.BOOLEAN, - description = "If true, initiates copy of scripts and restart of the agent if if the template version is the latest." + + description = "If true, initiates copy of scripts and restart of the agent, even if the scripts version matches." + "To be used with ID parameter only") private Boolean force; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java index 445130c4c333..52d659e1449d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java @@ -59,7 +59,7 @@ public class RestartNetworkCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.MAKEREDUNDANT, type = CommandType.BOOLEAN, required = false, description = "Turn the network into a network with redundant routers.", since = "4.11.1") private Boolean makeRedundant = false; - @Parameter(name = ApiConstants.LIVE_PATCH, type = CommandType.BOOLEAN, required = false, description = "Live Patch the router before restarting it", since = "4.16.1") + @Parameter(name = ApiConstants.LIVE_PATCH, type = CommandType.BOOLEAN, required = false, description = "Live Patch the router before restarting it. This parameter will work only when 'cleanup' is false.", since = "4.16.1") private Boolean livePatch = false; ///////////////////////////////////////////////////// diff --git a/core/src/main/java/com/cloud/resource/ServerResourceBase.java b/core/src/main/java/com/cloud/resource/ServerResourceBase.java index d8db1fd64605..99c9e2ee1058 100644 --- a/core/src/main/java/com/cloud/resource/ServerResourceBase.java +++ b/core/src/main/java/com/cloud/resource/ServerResourceBase.java @@ -33,8 +33,8 @@ import javax.naming.ConfigurationException; -import com.cloud.utils.EncryptionUtil; import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.cloudstack.utils.security.DigestHelper; import org.apache.log4j.Logger; import com.cloud.agent.IAgentControl; @@ -315,7 +315,7 @@ public String calculateCurrentChecksum(String name, String path) { if (cloudScriptsPath == null) { throw new CloudRuntimeException(String.format("Unable to find cloudScripts path, cannot update SystemVM %s", name)); } - String md5sum = EncryptionUtil.calculateChecksum(new File(cloudScriptsPath)); + String md5sum = DigestHelper.calculateChecksum(new File(cloudScriptsPath)); return md5sum; } } diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index 72073e92484f..ce80f4836bab 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -3300,6 +3300,10 @@ public boolean restartNetwork(final Long networkId, final Account callerAccount, for (DomainRouterVO router: domainRouters) { try { VMInstanceVO instanceVO = _vmDao.findById(router.getId()); + if (instanceVO == null) { + s_logger.info("Did not find a virtual router instance for the network"); + continue; + } Pair patched = mgr.updateSystemVM(instanceVO, true); if (patched.first()) { s_logger.info(String.format("Successfully patched router %s", router)); diff --git a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java index 4119b11ae508..214243886997 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java @@ -36,7 +36,6 @@ import com.cloud.upgrade.dao.BasicTemplateDataStoreDaoImpl; import com.cloud.user.Account; import com.cloud.utils.DateUtil; -import com.cloud.utils.EncryptionUtil; import com.cloud.utils.Pair; import com.cloud.utils.UriUtils; import com.cloud.utils.db.GlobalLock; @@ -55,6 +54,7 @@ import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; +import org.apache.cloudstack.utils.security.DigestHelper; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.ini4j.Ini; @@ -679,6 +679,12 @@ public void registerTemplate(Pair hypervisorA } } + /** + * This method parses the metadata file consisting of the systemVM templates information + * @return the version of the systemvm template that is to be used. This is done to in order + * to fallback on the latest available version of the systemVM template when there does not + * exist a template corresponding to the current code version. + */ public static String parseMetadataFile() { try { Ini ini = new Ini(); @@ -726,7 +732,7 @@ private void validateTemplates(Set hypervisorsInUse) } File tempFile = new File(TEMPLATES_PATH + matchedTemplate); - String templateChecksum = EncryptionUtil.calculateChecksum(tempFile); + String templateChecksum = DigestHelper.calculateChecksum(tempFile); if (!templateChecksum.equals(NewTemplateChecksum.get(getHypervisorType(hypervisor)))) { LOGGER.error(String.format("Checksum mismatch: %s != %s ", templateChecksum, NewTemplateChecksum.get(getHypervisorType(hypervisor)))); templatesFound = false; diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java index c11b19cb1efc..d79adb7d28fc 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java @@ -32,12 +32,11 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.google.common.base.Strings; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.annotation.AnnotationService; @@ -428,22 +427,19 @@ private boolean validateServiceOffering(final ServiceOffering serviceOffering, f private void validateDockerRegistryParams(final String dockerRegistryUserName, final String dockerRegistryPassword, - final String dockerRegistryUrl, - final String dockerRegistryEmail) { + final String dockerRegistryUrl) { // if no params related to docker registry specified then nothing to validate so return true if ((dockerRegistryUserName == null || dockerRegistryUserName.isEmpty()) && (dockerRegistryPassword == null || dockerRegistryPassword.isEmpty()) && - (dockerRegistryUrl == null || dockerRegistryUrl.isEmpty()) && - (dockerRegistryEmail == null || dockerRegistryEmail.isEmpty())) { + (dockerRegistryUrl == null || dockerRegistryUrl.isEmpty())) { return; } // all params related to docker registry must be specified or nothing if (!((dockerRegistryUserName != null && !dockerRegistryUserName.isEmpty()) && (dockerRegistryPassword != null && !dockerRegistryPassword.isEmpty()) && - (dockerRegistryUrl != null && !dockerRegistryUrl.isEmpty()) && - (dockerRegistryEmail != null && !dockerRegistryEmail.isEmpty()))) { - throw new InvalidParameterValueException("All the docker private registry parameters (username, password, url, email) required are specified"); + (dockerRegistryUrl != null && !dockerRegistryUrl.isEmpty()))) { + throw new InvalidParameterValueException("All the docker private registry parameters (username, password, url) required are specified"); } try { @@ -451,12 +447,6 @@ private void validateDockerRegistryParams(final String dockerRegistryUserName, } catch (MalformedURLException e) { throw new InvalidParameterValueException("Invalid docker registry url specified"); } - - Pattern VALID_EMAIL_ADDRESS_REGEX = Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", Pattern.CASE_INSENSITIVE); - Matcher matcher = VALID_EMAIL_ADDRESS_REGEX.matcher(dockerRegistryEmail); - if (!matcher.find()) { - throw new InvalidParameterValueException("Invalid docker registry email specified"); - } } private DeployDestination plan(final long nodesCount, final DataCenter zone, final ServiceOffering offering) throws InsufficientServerCapacityException { @@ -619,7 +609,6 @@ private void validateKubernetesClusterCreateParameters(final CreateKubernetesClu final String dockerRegistryUserName = cmd.getDockerRegistryUserName(); final String dockerRegistryPassword = cmd.getDockerRegistryPassword(); final String dockerRegistryUrl = cmd.getDockerRegistryUrl(); - final String dockerRegistryEmail = cmd.getDockerRegistryEmail(); final Long nodeRootDiskSize = cmd.getNodeRootDiskSize(); final String externalLoadBalancerIpAddress = cmd.getExternalLoadBalancerIpAddress(); @@ -706,7 +695,7 @@ private void validateKubernetesClusterCreateParameters(final CreateKubernetesClu throw new InvalidParameterValueException("Given service offering ID: %s is not suitable for Kubernetes cluster"); } - validateDockerRegistryParams(dockerRegistryUserName, dockerRegistryPassword, dockerRegistryUrl, dockerRegistryEmail); + validateDockerRegistryParams(dockerRegistryUserName, dockerRegistryPassword, dockerRegistryUrl); Network network = null; if (networkId != null) { @@ -728,7 +717,8 @@ private void validateKubernetesClusterCreateParameters(final CreateKubernetesClu } } - if (!KubernetesClusterExperimentalFeaturesEnabled.value() && !StringUtils.isAllEmpty(dockerRegistryUrl, dockerRegistryUserName, dockerRegistryEmail, dockerRegistryPassword)) { + if (!KubernetesClusterExperimentalFeaturesEnabled.value() && (!Strings.isNullOrEmpty(dockerRegistryUrl) || + !Strings.isNullOrEmpty(dockerRegistryUserName) || !Strings.isNullOrEmpty(dockerRegistryPassword))) { throw new CloudRuntimeException(String.format("Private registry for the Kubernetes cluster is an experimental feature. Use %s configuration for enabling experimental features", KubernetesClusterExperimentalFeaturesEnabled.key())); } } @@ -778,7 +768,6 @@ private void addKubernetesClusterDetails(final KubernetesCluster kubernetesClust final String dockerRegistryUserName = cmd.getDockerRegistryUserName(); final String dockerRegistryPassword = cmd.getDockerRegistryPassword(); final String dockerRegistryUrl = cmd.getDockerRegistryUrl(); - final String dockerRegistryEmail = cmd.getDockerRegistryEmail(); final boolean networkCleanup = cmd.getNetworkId() == null; Transaction.execute(new TransactionCallbackNoReturn() { @Override @@ -793,9 +782,8 @@ public void doInTransactionWithoutResult(TransactionStatus status) { addKubernetesClusterDetailIfIsNotEmpty(details, kubernetesClusterId, ApiConstants.DOCKER_REGISTRY_USER_NAME, dockerRegistryUserName, true); addKubernetesClusterDetailIfIsNotEmpty(details, kubernetesClusterId, ApiConstants.DOCKER_REGISTRY_PASSWORD, dockerRegistryPassword, false); addKubernetesClusterDetailIfIsNotEmpty(details, kubernetesClusterId, ApiConstants.DOCKER_REGISTRY_URL, dockerRegistryUrl, true); - addKubernetesClusterDetailIfIsNotEmpty(details, kubernetesClusterId, ApiConstants.DOCKER_REGISTRY_EMAIL, dockerRegistryEmail, true); - details.add(new KubernetesClusterDetailsVO(kubernetesClusterId, ApiConstants.USERNAME, "admin", true)); + details.add(new KubernetesClusterDetailsVO(kubernetesCluster.getId(), ApiConstants.USERNAME, "admin", true)); SecureRandom random = new SecureRandom(); String randomPassword = new BigInteger(130, random).toString(32); details.add(new KubernetesClusterDetailsVO(kubernetesClusterId, ApiConstants.PASSWORD, randomPassword, false)); diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java index 8a6c81e23ee1..591b90178939 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java @@ -28,6 +28,7 @@ import javax.inject.Inject; +import com.google.common.base.Strings; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.command.user.firewall.CreateFirewallRuleCmd; @@ -35,6 +36,7 @@ import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd; import org.apache.commons.codec.binary.Base64; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Level; import com.cloud.capacity.CapacityManager; @@ -95,7 +97,6 @@ import com.cloud.vm.UserVmManager; import com.cloud.vm.VirtualMachine; import com.cloud.vm.dao.VMInstanceDao; -import org.apache.commons.lang3.StringUtils; import static com.cloud.utils.NumbersUtil.toHumanReadableSize; @@ -163,54 +164,48 @@ private String getKubernetesNodeConfig(final String joinIp, final boolean ejectI k8sNodeConfig = k8sNodeConfig.replace(joinIpKey, joinIp); k8sNodeConfig = k8sNodeConfig.replace(clusterTokenKey, KubernetesClusterUtil.generateClusterToken(kubernetesCluster)); k8sNodeConfig = k8sNodeConfig.replace(ejectIsoKey, String.valueOf(ejectIso)); - /* genarate /.docker/config.json file on the nodes only if Kubernetes cluster is created to + + k8sNodeConfig = updateKubeConfigWithRegistryDetails(k8sNodeConfig); + return k8sNodeConfig; + } + + protected String updateKubeConfigWithRegistryDetails(String k8sConfig) { + /* genarate /etc/containerd/config.toml file on the nodes only if Kubernetes cluster is created to * use docker private registry */ - String dockerUserName = null; - String dockerPassword = null; - String dockerRegistryUrl = null; - String dockerRegistryEmail = null; + String registryUsername = null; + String registryPassword = null; + String registryUrl = null; + List details = kubernetesClusterDetailsDao.listDetails(kubernetesCluster.getId()); for (KubernetesClusterDetailsVO detail : details) { if (detail.getName().equals(ApiConstants.DOCKER_REGISTRY_USER_NAME)) { - dockerUserName = detail.getValue(); + registryUsername = detail.getValue(); } if (detail.getName().equals(ApiConstants.DOCKER_REGISTRY_PASSWORD)) { - dockerPassword = detail.getValue(); + registryPassword = detail.getValue(); } if (detail.getName().equals(ApiConstants.DOCKER_REGISTRY_URL)) { - dockerRegistryUrl = detail.getValue(); - } - if (detail.getName().equals(ApiConstants.DOCKER_REGISTRY_EMAIL)) { - dockerRegistryEmail = detail.getValue(); + registryUrl = detail.getValue(); } } - if (StringUtils.isNoneEmpty(dockerUserName, dockerPassword)) { - // do write file for /.docker/config.json through the code instead of k8s-node.yml as we can no make a section - // optional or conditionally applied - String dockerConfigString = "write_files:\n" + - " - path: /.docker/config.json\n" + - " owner: cloud:cloud\n" + - " permissions: '0644'\n" + - " content: |\n" + - " {\n" + - " \"auths\": {\n" + - " {{docker.url}}: {\n" + - " \"auth\": {{docker.secret}},\n" + - " \"email\": {{docker.email}}\n" + - " }\n" + - " }\n" + - " }"; - k8sNodeConfig = k8sNodeConfig.replace("write_files:", dockerConfigString); - final String dockerUrlKey = "{{docker.url}}"; - final String dockerAuthKey = "{{docker.secret}}"; - final String dockerEmailKey = "{{docker.email}}"; - final String usernamePasswordKey = dockerUserName + ":" + dockerPassword; - String base64Auth = Base64.encodeBase64String(usernamePasswordKey.getBytes(com.cloud.utils.StringUtils.getPreferredCharset())); - k8sNodeConfig = k8sNodeConfig.replace(dockerUrlKey, "\"" + dockerRegistryUrl + "\""); - k8sNodeConfig = k8sNodeConfig.replace(dockerAuthKey, "\"" + base64Auth + "\""); - k8sNodeConfig = k8sNodeConfig.replace(dockerEmailKey, "\"" + dockerRegistryEmail + "\""); + + if (!Strings.isNullOrEmpty(registryUsername) && !Strings.isNullOrEmpty(registryPassword) && !Strings.isNullOrEmpty(registryUrl)) { + // Update runcmd in the cloud-init configuration to run a script that updates the containerd config with provided registry details + String runCmd = "- bash -x /opt/bin/setup-containerd"; + + String registryEp = registryUrl.split("://")[1]; + k8sConfig = k8sConfig.replace("- containerd config default > /etc/containerd/config.toml", runCmd); + final String registryUrlKey = "{{registry.url}}"; + final String registryUrlEpKey = "{{registry.url.endpoint}}"; + final String registryAuthKey = "{{registry.token}}"; + + final String usernamePasswordKey = registryUsername + ":" + registryPassword; + String base64Auth = Base64.encodeBase64String(usernamePasswordKey.getBytes((com.cloud.utils.StringUtils.getPreferredCharset()))); + k8sConfig = k8sConfig.replace(registryUrlKey, registryUrl); + k8sConfig = k8sConfig.replace(registryUrlEpKey, registryEp); + k8sConfig = k8sConfig.replace(registryAuthKey, base64Auth); } - return k8sNodeConfig; + return k8sConfig; } protected DeployDestination plan(final long nodesCount, final DataCenter zone, final ServiceOffering offering) throws InsufficientServerCapacityException { diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java index 9bed248f7b52..e2496a04c25b 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java @@ -174,6 +174,7 @@ private String getKubernetesControlNodeConfig(final String controlNodeIp, final initArgs += String.format(" --kubernetes-version=%s", getKubernetesClusterVersion().getSemanticVersion()); k8sControlNodeConfig = k8sControlNodeConfig.replace(clusterInitArgsKey, initArgs); k8sControlNodeConfig = k8sControlNodeConfig.replace(ejectIsoKey, String.valueOf(ejectIso)); + k8sControlNodeConfig = updateKubeConfigWithRegistryDetails(k8sControlNodeConfig); return k8sControlNodeConfig; } @@ -236,6 +237,7 @@ private String getKubernetesAdditionalControlNodeConfig(final String joinIp, fin k8sControlNodeConfig = k8sControlNodeConfig.replace(clusterTokenKey, KubernetesClusterUtil.generateClusterToken(kubernetesCluster)); k8sControlNodeConfig = k8sControlNodeConfig.replace(clusterHACertificateKey, KubernetesClusterUtil.generateClusterHACertificateKey(kubernetesCluster)); k8sControlNodeConfig = k8sControlNodeConfig.replace(ejectIsoKey, String.valueOf(ejectIso)); + k8sControlNodeConfig = updateKubeConfigWithRegistryDetails(k8sControlNodeConfig); return k8sControlNodeConfig; } diff --git a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/CreateKubernetesClusterCmd.java b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/CreateKubernetesClusterCmd.java index 376c148abb7a..64de4669f870 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/CreateKubernetesClusterCmd.java +++ b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/CreateKubernetesClusterCmd.java @@ -140,10 +140,6 @@ public class CreateKubernetesClusterCmd extends BaseAsyncCreateCmd { description = "URL for the docker image private registry") private String dockerRegistryUrl; - @Parameter(name = ApiConstants.DOCKER_REGISTRY_EMAIL, type = CommandType.STRING, - description = "email of the docker image private registry user") - private String dockerRegistryEmail; - @Parameter(name = ApiConstants.NODE_ROOT_DISK_SIZE, type = CommandType.LONG, description = "root disk size in GB for each node") private Long nodeRootDiskSize; @@ -226,10 +222,6 @@ public String getDockerRegistryUrl() { return dockerRegistryUrl; } - public String getDockerRegistryEmail() { - return dockerRegistryEmail; - } - public Long getNodeRootDiskSize() { if (nodeRootDiskSize != null) { if (nodeRootDiskSize < DEFAULT_NODE_ROOT_DISK_SIZE) { diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml index db295188eba5..480e7bba8526 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml @@ -213,6 +213,23 @@ write_files: sudo touch /home/cloud/success echo "true" > /home/cloud/success + - path: /opt/bin/setup-containerd + permissions: '0755' + owner: root:root + content: | + #!/bin/bash -e + + export registryConfig="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.mirrors.\"{{registry.url.endpoint}}\"]\n \\ endpoint = [\"{{registry.url}}\"]" + export registryCredentials="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.configs.\"{{registry.url}}\".auth]\n \tauth = \"\" \n \tidentitytoken = \"{{registry.token}}\"" + + echo "creating config file for containerd" + containerd config default > /etc/containerd/config.toml + sed -i '/\[plugins."io.containerd.grpc.v1.cri".registry\]/a '"${registryCredentials}"'' /etc/containerd/config.toml + sed -i '/\[plugins."io.containerd.grpc.v1.cri".registry.mirrors\]/a '"${registryConfig}"'' /etc/containerd/config.toml + + echo "Restarting containerd service" + systemctl restart containerd + - path: /etc/systemd/system/setup-kube-system.service permissions: '0755' owner: root:root @@ -242,6 +259,8 @@ write_files: runcmd: - chown -R cloud:cloud /home/cloud/.ssh + - containerd config default > /etc/containerd/config.toml + - systemctl restart containerd - [ systemctl, start, setup-kube-system ] - [ systemctl, start, deploy-kube-system ] diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml index 730477bd4eef..ceca597516fa 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml @@ -270,6 +270,23 @@ write_files: sudo touch /home/cloud/success echo "true" > /home/cloud/success + - path: /opt/bin/setup-containerd + permissions: '0755' + owner: root:root + content: | + #!/bin/bash -e + + export registryConfig="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.mirrors.\"{{registry.url.endpoint}}\"]\n \\ endpoint = [\"{{registry.url}}\"]" + export registryCredentials="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.configs.\"{{registry.url.endpoint}}\".auth]\n \tauth = \"\" \n \tidentitytoken = \"{{registry.token}}\"" + + echo "creating config file for containerd" + containerd config default > /etc/containerd/config.toml + sed -i '/\[plugins."io.containerd.grpc.v1.cri".registry\]/a '"${registryCredentials}"'' /etc/containerd/config.toml + sed -i '/\[plugins."io.containerd.grpc.v1.cri".registry.mirrors\]/a '"${registryConfig}"'' /etc/containerd/config.toml + + echo "Restarting containerd service" + systemctl restart containerd + - path: /etc/systemd/system/setup-kube-system.service permissions: '0755' owner: root:root @@ -299,6 +316,8 @@ write_files: runcmd: - chown -R cloud:cloud /home/cloud/.ssh + - containerd config default > /etc/containerd/config.toml + - systemctl restart containerd - [ systemctl, start, setup-kube-system ] - [ systemctl, start, deploy-kube-system ] diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml index eea369921ac8..b6a71e8deb2e 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml @@ -213,6 +213,23 @@ write_files: sudo touch /home/cloud/success echo "true" > /home/cloud/success + - path: /opt/bin/setup-containerd + permissions: '0755' + owner: root:root + content: | + #!/bin/bash -e + + export registryConfig="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.mirrors.\"{{registry.url.endpoint}}\"]\n \\ endpoint = [\"{{registry.url}}\"]" + export registryCredentials="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.configs.\"{{registry.url}}\".auth]\n \tauth = \"\" \n \tidentitytoken = \"{{registry.token}}\"" + + echo "creating config file for containerd" + containerd config default > /etc/containerd/config.toml + sed -i '/\[plugins."io.containerd.grpc.v1.cri".registry\]/a '"${registryCredentials}"'' /etc/containerd/config.toml + sed -i '/\[plugins."io.containerd.grpc.v1.cri".registry.mirrors\]/a '"${registryConfig}"'' /etc/containerd/config.toml + + echo "Restarting containerd service" + systemctl restart containerd + - path: /etc/systemd/system/setup-kube-system.service permissions: '0755' owner: root:root @@ -242,5 +259,7 @@ write_files: runcmd: - chown -R cloud:cloud /home/cloud/.ssh + - containerd config default > /etc/containerd/config.toml + - systemctl restart containerd - [ systemctl, start, setup-kube-system ] - [ systemctl, start, deploy-kube-system ] diff --git a/systemvm/debian/opt/cloud/bin/setup/cksnode.sh b/systemvm/debian/opt/cloud/bin/setup/cksnode.sh index 78ae96631ad9..0b5df04ded2b 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cksnode.sh +++ b/systemvm/debian/opt/cloud/bin/setup/cksnode.sh @@ -31,15 +31,10 @@ setup_k8s_node() { systemctl restart ssh # Prevent root login -# > /root/.ssh/authorized_keys -# passwd -l root + > /root/.ssh/authorized_keys + passwd -l root #sed -i 's#root:x:0:0:root:/root:/bin/bash#root:x:0:0:root:/root:/sbin/nologin#' /etc/passwd - # Update containerd configuration - mkdir -p /etc/containerd - containerd config default>/etc/containerd/config.toml - systemctl restart containerd - swapoff -a sudo sed -i '/ swap / s/^/#/' /etc/fstab log_it "Swap disabled" diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 76e2f35ced56..ae67155f753f 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -230,6 +230,8 @@ "label.action.migrate.systemvm": "Migrate System VM", "label.action.migrate.systemvm.processing": "Migrating System VM....", "label.action.migrate.systemvm.to.ps": "Migrate system VM to another primary storage", +"label.action.patch.systemvm": "Patch System VM", +"label.action.patch.systemvm.processing": "Patching System VM....", "label.action.project.add.account": "Add Account to Project", "label.action.project.add.user": "Add User to Project", "label.action.reboot.instance": "Reboot Instance", @@ -1317,6 +1319,7 @@ "label.list.nodes": "List nodes", "label.list.pods": "List pods", "label.list.services": "List services", +"label.livepatch": "Live Patch network's router(s)", "label.load.balancer": "Load Balancer", "label.load.balancing.policies": "Load balancing policies", "label.loadbalancerinstance": "Assigned VMs", @@ -2562,6 +2565,7 @@ "message.action.host.enable.maintenance.mode": "Enabling maintenance mode will cause a live migration of all running instances on this host to any available host.", "message.action.instance.reset.password": "Please confirm that you want to change the ROOT password for this virtual machine.", "message.action.manage.cluster": "Please confirm that you want to manage the cluster.", +"message.action.patch.systemvm": "Please confirm that you want to patch the System VM.", "message.action.primarystorage.enable.maintenance.mode": "Warning: placing the primary storage into maintenance mode will cause all VMs using volumes from it to be stopped. Do you want to continue?", "message.action.reboot.instance": "Please confirm that you want to reboot this instance.", "message.action.reboot.router": "All services provided by this virtual router will be interrupted. Please confirm that you want to reboot this router.", diff --git a/ui/src/config/section/image.js b/ui/src/config/section/image.js index 360525397f6e..3bd6d578cd75 100644 --- a/ui/src/config/section/image.js +++ b/ui/src/config/section/image.js @@ -100,7 +100,6 @@ export default { return (['Admin'].includes(store.userInfo.roletype) || // If admin or owner or belongs to current project (record.domainid === store.userInfo.domainid && record.account === store.userInfo.account) || (record.domainid === store.userInfo.domainid && record.projectid && store.project && store.project.id && record.projectid === store.project.id)) && - record.templatetype !== 'SYSTEM' && record.isready }, popup: true, diff --git a/ui/src/config/section/infra/systemVms.js b/ui/src/config/section/infra/systemVms.js index 2c0bd1d6e593..acd1f1959787 100644 --- a/ui/src/config/section/infra/systemVms.js +++ b/ui/src/config/section/infra/systemVms.js @@ -135,6 +135,18 @@ export default { }, response: (result) => { return result && result.diagnostics && result.diagnostics.url ? `Please click the link to download the retrieved diagnostics:

${result.diagnostics.url}

` : 'Invalid response' } }, + { + api: 'patchSystemVm', + icon: 'diff', + label: 'label.action.patch.systemvm', + message: 'message.action.patch.systemvm', + dataView: true, + show: (record) => { return ['Running'].includes(record.state) }, + args: ['forced'], + groupAction: true, + popup: true, + groupMap: (selection) => { return selection.map(x => { return { id: x } }) } + }, { api: 'destroySystemVm', icon: 'delete', diff --git a/ui/src/views/compute/CreateKubernetesCluster.vue b/ui/src/views/compute/CreateKubernetesCluster.vue index 6b6b81f67918..52aa831d75c5 100644 --- a/ui/src/views/compute/CreateKubernetesCluster.vue +++ b/ui/src/views/compute/CreateKubernetesCluster.vue @@ -226,14 +226,6 @@ }]" :placeholder="apiParams.dockerregistryurl.description"/> - - - -
diff --git a/utils/src/main/java/com/cloud/utils/EncryptionUtil.java b/utils/src/main/java/com/cloud/utils/EncryptionUtil.java index ff791a3f5226..b82842e947b6 100644 --- a/utils/src/main/java/com/cloud/utils/EncryptionUtil.java +++ b/utils/src/main/java/com/cloud/utils/EncryptionUtil.java @@ -18,12 +18,7 @@ */ package com.cloud.utils; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; import java.io.UnsupportedEncodingException; -import java.nio.file.Files; -import java.nio.file.Paths; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -31,7 +26,6 @@ import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; -import org.apache.commons.codec.digest.DigestUtils; import org.apache.log4j.Logger; import org.jasypt.encryption.pbe.PBEStringEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; @@ -76,14 +70,4 @@ public static String generateSignature(String data, String key) { throw new CloudRuntimeException("unable to generate signature", e); } } - - public static String calculateChecksum(File file) { - try (InputStream is = Files.newInputStream(Paths.get(file.getPath()))) { - return DigestUtils.md5Hex(is); - } catch (IOException e) { - String errMsg = "Failed to calculate template checksum"; - s_logger.error(errMsg, e); - throw new CloudRuntimeException(errMsg, e); - } - } } diff --git a/utils/src/main/java/org/apache/cloudstack/utils/security/DigestHelper.java b/utils/src/main/java/org/apache/cloudstack/utils/security/DigestHelper.java index 8fd8e8f338ef..7e4e80f8f4d2 100644 --- a/utils/src/main/java/org/apache/cloudstack/utils/security/DigestHelper.java +++ b/utils/src/main/java/org/apache/cloudstack/utils/security/DigestHelper.java @@ -17,10 +17,17 @@ package org.apache.cloudstack.utils.security; import org.apache.commons.lang3.StringUtils; +import com.cloud.utils.EncryptionUtil; +import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.log4j.Logger; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; +import java.nio.file.Files; +import java.nio.file.Paths; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.HashMap; @@ -28,6 +35,8 @@ public class DigestHelper { + public static final Logger LOGGER = Logger.getLogger(EncryptionUtil.class.getName()); + public static ChecksumValue digest(String algorithm, InputStream is) throws NoSuchAlgorithmException, IOException { MessageDigest digest = MessageDigest.getInstance(algorithm); ChecksumValue checksum = null; @@ -131,4 +140,14 @@ protected static boolean isAlgorithmPresent(String checksum) { public static String getHashValueFromChecksumValue(String checksum) { return isAlgorithmPresent(checksum) ? new ChecksumValue(checksum).getChecksum() : checksum; } + + public static String calculateChecksum(File file) { + try (InputStream is = Files.newInputStream(Paths.get(file.getPath()))) { + return DigestUtils.md5Hex(is); + } catch (IOException e) { + String errMsg = "Failed to calculate template checksum"; + LOGGER.error(errMsg, e); + throw new CloudRuntimeException(errMsg, e); + } + } } From e6f9c29de8fb2343361e3f1c7242596f05c7c8e9 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Wed, 19 Jan 2022 16:35:01 +0530 Subject: [PATCH 42/68] test: validate performance for template modification during seeding --- .../upgrade/SystemVmTemplateRegistration.java | 18 +++++++ .../systemd/cloudstack-management.service | 1 - .../cluster/KubernetesClusterManagerImpl.java | 4 +- ...esClusterResourceModifierActionWorker.java | 3 +- pom.xml | 2 +- scripts/installer/export-templates.sh | 54 +++++++++++++++---- .../apache/cloudstack/ca/CAManagerImpl.java | 3 +- tools/appliance/build.sh | 8 +-- 8 files changed, 70 insertions(+), 23 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java index 214243886997..2df2de44995e 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java @@ -93,6 +93,7 @@ public class SystemVmTemplateRegistration { public static final String TEMPORARY_SECONDARY_STORE = "tmp"; private static final String PARTIAL_TEMPLATE_FOLDER = String.format("/template/tmpl/%d/", Account.ACCOUNT_ID_SYSTEM); private static final String storageScriptsDir = "scripts/storage/secondary"; + private static final String installerScriptsDir = "scripts/installer/"; private static final Integer OTHER_LINUX_ID = 99; private static final Integer LINUX_5_ID = 15; private static final Integer LINUX_7_ID = 183; @@ -724,6 +725,7 @@ private void validateTemplates(Set hypervisorsInUse) } boolean templatesFound = true; + int count = hypervisors.size(); for (String hypervisor : hypervisors) { String matchedTemplate = templates.stream().filter(x -> x.contains(hypervisor)).findAny().orElse(null); if (matchedTemplate == null) { @@ -732,6 +734,22 @@ private void validateTemplates(Set hypervisorsInUse) } File tempFile = new File(TEMPLATES_PATH + matchedTemplate); + if (!tempFile.exists()) { + --count; + String exportTmpltScript = Script.findScript(installerScriptsDir, "export-templates.sh"); + if (exportTmpltScript == null) { + throw new CloudRuntimeException("Unable to find the export-templates.sh script to export templates on the fly"); + } + Script scr = new Script(exportTmpltScript, SCRIPT_TIMEOUT, LOGGER); + scr.add(hypervisor.toLowerCase(Locale.ROOT)); + scr.add((count > 0 ? "1" : "0")); + String result = scr.execute(); + if (result != null) { + String errMsg = String.format("failed to create template: %s ", result); + LOGGER.error(errMsg); + throw new CloudRuntimeException(errMsg); + } + } String templateChecksum = DigestHelper.calculateChecksum(tempFile); if (!templateChecksum.equals(NewTemplateChecksum.get(getHypervisorType(hypervisor)))) { LOGGER.error(String.format("Checksum mismatch: %s != %s ", templateChecksum, NewTemplateChecksum.get(getHypervisorType(hypervisor)))); diff --git a/packaging/systemd/cloudstack-management.service b/packaging/systemd/cloudstack-management.service index aedd3a170ae4..db94a42d6439 100644 --- a/packaging/systemd/cloudstack-management.service +++ b/packaging/systemd/cloudstack-management.service @@ -34,7 +34,6 @@ User=cloud EnvironmentFile=/etc/default/cloudstack-management WorkingDirectory=/var/log/cloudstack/management PIDFile=/var/run/cloudstack-management.pid -ExecStartPre=/bin/bash /usr/share/cloudstack-management/templates/systemvm/export-templates.sh ExecStart=/usr/bin/java $JAVA_DEBUG $JAVA_OPTS -cp $CLASSPATH $BOOTSTRAP_CLASS TimeoutSec=900 diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java index d79adb7d28fc..c19968d43662 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java @@ -36,7 +36,6 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.google.common.base.Strings; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.annotation.AnnotationService; @@ -717,8 +716,7 @@ private void validateKubernetesClusterCreateParameters(final CreateKubernetesClu } } - if (!KubernetesClusterExperimentalFeaturesEnabled.value() && (!Strings.isNullOrEmpty(dockerRegistryUrl) || - !Strings.isNullOrEmpty(dockerRegistryUserName) || !Strings.isNullOrEmpty(dockerRegistryPassword))) { + if (!KubernetesClusterExperimentalFeaturesEnabled.value() && !StringUtils.isAllEmpty(dockerRegistryUrl, dockerRegistryUserName, dockerRegistryPassword)) { throw new CloudRuntimeException(String.format("Private registry for the Kubernetes cluster is an experimental feature. Use %s configuration for enabling experimental features", KubernetesClusterExperimentalFeaturesEnabled.key())); } } diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java index 591b90178939..98e4587dff37 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java @@ -28,7 +28,6 @@ import javax.inject.Inject; -import com.google.common.base.Strings; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.command.user.firewall.CreateFirewallRuleCmd; @@ -189,7 +188,7 @@ protected String updateKubeConfigWithRegistryDetails(String k8sConfig) { } } - if (!Strings.isNullOrEmpty(registryUsername) && !Strings.isNullOrEmpty(registryPassword) && !Strings.isNullOrEmpty(registryUrl)) { + if (StringUtils.isNoneEmpty(registryUsername, registryPassword, registryUrl)) { // Update runcmd in the cloud-init configuration to run a script that updates the containerd config with provided registry details String runCmd = "- bash -x /opt/bin/setup-containerd"; diff --git a/pom.xml b/pom.xml index 4daaa8ccfca5..a704d520c097 100644 --- a/pom.xml +++ b/pom.xml @@ -49,7 +49,7 @@ UTF-8 UTF-8 - 4.16.1.0 + 4.17.0.0 11 diff --git a/scripts/installer/export-templates.sh b/scripts/installer/export-templates.sh index 578854df437a..9371f1c74128 100644 --- a/scripts/installer/export-templates.sh +++ b/scripts/installer/export-templates.sh @@ -17,21 +17,27 @@ # under the License. METADATA_FILE="metadata.ini" -IMAGE_PATH=${1:-"/usr/share/cloudstack-management/templates/systemvm/"} +IMAGE_PATH=${3:-"/usr/share/cloudstack-management/templates/systemvm/"} TEMPLATE_VERSION=$(awk -F "=" '/version/ {print $2}' ${IMAGE_PATH}${METADATA_FILE} | xargs) TEMPLATE_PATH="/usr/share/cloudstack-management/templates/systemvm/" VERSION="${TEMPLATE_VERSION%.*}" -PREFIX=${2:-"systemvmtemplate-$VERSION"} +PREFIX=${4:-"systemvmtemplate-$VERSION"} +CLEANUP=${2:-1} TEMP_IMAGE_PATH="/tmp/sysvm_convert/" -if [ -f ${IMAGE_PATH}${PREFIX}-kvm.qcow2.bxz2 ]; then +initial_setup() { mkdir -p $TEMP_IMAGE_PATH cp -r $IMAGE_PATH/* $TEMP_IMAGE_PATH cd $TEMP_IMAGE_PATH - bzip2 -dc $PREFIX-kvm.qcow2.bz2 > $PREFIX-kvm.qcow2 + if [ ! -f ${TEMP_IMAGE_PATH}${PREFIX}-kvm.qcow2 ]; then + bzip2 -dc $PREFIX-kvm.qcow2.bz2 > $PREFIX-kvm.qcow2 + fi +} + +export_vmware() { + initial_setup # Export for KVM virt-sparsify $PREFIX-kvm.qcow2 --compress -o compat=0.10 $PREFIX-kvm-temp.qcow2 - # Export for VMware qemu-img convert -f qcow2 -O vmdk -o adapter_type=lsilogic,subformat=streamOptimized,compat6 $PREFIX-kvm-temp.qcow2 $PREFIX-vmware.vmdk size=$(stat --printf="%s" $PREFIX-vmware.vmdk) @@ -144,15 +150,43 @@ EOF tar -cvf $PREFIX-vmware.ova $PREFIX-vmware.ovf $PREFIX-vmware.mf $PREFIX-vmware.vmdk checksum=$(md5sum $PREFIX-vmware.ova | awk '{print $1}') sed -i '/^\['"vmware"']/,/^\[/{s/^checksum[[:space:]]*=.*/checksum = '"$checksum"'/}' ./$METADATA_FILE + rm -rf *.mf *.ovf *.vmdk + sudo cp $TEMP_IMAGE_PATH/$PREFIX-vmware.ova $TEMP_IMAGE_PATH/metadata.ini $IMAGE_PATH + cleanup +} +export_xen() { # Export for XenServer/XCP-ng + initial_setup qemu-img convert -f qcow2 -O vpc $PREFIX-kvm.qcow2 $PREFIX-xen.vhd bzip2 $PREFIX-xen.vhd checksum=$(md5sum $PREFIX-xen.vhd.bz2 | awk '{print $1}') sed -i '/^\['"xenserver"']/,/^\[/{s/^checksum[[:space:]]*=.*/checksum = '"$checksum"'/}' $METADATA_FILE + rm -rf $PREFIX-xen.vhd + sudo cp $TEMP_IMAGE_PATH/$PREFIX-xen* $TEMP_IMAGE_PATH/metadata.ini $IMAGE_PATH + cleanup +} + +cleanup() { + cd /var/cloudstack/management/ + if [ $CLEANUP == 1 ]; then + cd /var/cloudstack/management/ + rm -rf $TEMP_IMAGE_PATH + fi +} + +if [ "$#" -lt 1 ] ; then + echo "Usage: $0 [cleanup: 0/1; default: 1] [imagepath: default:/usr/share/cloudstack-management/templates/systemvm/] [templateprefix: default:systemvmtemplate-$VERSION]" >&2 + exit 1 +fi + +if [ $1 == "vmware" ]; then + echo "exporting vmware template" + export_vmware +elif [ $1 == "xenserver" ]; then + echo "exporting xenserver template" + export_xen +else + echo "Conversion of template to $1's compatible format not supported " +fi - rm -rf $PREFIX-kvm*.qcow2 $PREFIX-xen.vhd *.mf *.ovf *.vmdk - sudo cp $TEMP_IMAGE_PATH/$PREFIX* $TEMP_IMAGE_PATH/metadata.ini $IMAGE_PATH - cd - - rm -rf $TEMP_IMAGE_PATH -fi \ No newline at end of file diff --git a/server/src/main/java/org/apache/cloudstack/ca/CAManagerImpl.java b/server/src/main/java/org/apache/cloudstack/ca/CAManagerImpl.java index 5f4a16e1fe57..2e7e756c49a8 100644 --- a/server/src/main/java/org/apache/cloudstack/ca/CAManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/ca/CAManagerImpl.java @@ -39,7 +39,6 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; -import com.google.common.base.Strings; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.command.admin.ca.IssueCertificateCmd; @@ -190,7 +189,7 @@ public boolean provisionCertificate(final Host host, final Boolean reconnect, fi try { if (host.getType() != Host.Type.ConsoleProxy && host.getType() != Host.Type.SecondaryStorageVM) { csr = generateKeyStoreAndCsr(host, null); - if (Strings.isNullOrEmpty(csr)) { + if (StringUtils.isEmpty(csr)) { return false; } } diff --git a/tools/appliance/build.sh b/tools/appliance/build.sh index 285d818c0c75..1c83f9aba510 100755 --- a/tools/appliance/build.sh +++ b/tools/appliance/build.sh @@ -348,11 +348,11 @@ function main() { packer_build # process the disk at dist -# kvm_export -# ovm_export -# xen_server_export + kvm_export + ovm_export + xen_server_export vmware_export -# hyperv_export + hyperv_export rm -f "dist/${appliance}" cd dist && chmod +r * && cd .. cd dist && md5sum * > md5sum.txt && cd .. From ebfd912a3b9aa6ec5715ec2ff57b2de48c13f8ee Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Thu, 20 Jan 2022 10:29:59 +0530 Subject: [PATCH 43/68] create vms folder in cloudstack-commons directory - debian rules --- debian/rules | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/rules b/debian/rules index e216fc77a7e0..0d5dfb21e482 100755 --- a/debian/rules +++ b/debian/rules @@ -116,6 +116,7 @@ override_dh_auto_install: mkdir $(DESTDIR)/usr/share/$(PACKAGE)-common/scripts mkdir $(DESTDIR)/usr/share/$(PACKAGE)-common/setup mkdir $(DESTDIR)/usr/share/$(PACKAGE)-common/lib + mkdir $(DESTDIR)/usr/share/$(PACKAGE)-common/vms cp -r scripts/installer $(DESTDIR)/usr/share/$(PACKAGE)-common/scripts cp -r scripts/network $(DESTDIR)/usr/share/$(PACKAGE)-common/scripts cp -r scripts/storage $(DESTDIR)/usr/share/$(PACKAGE)-common/scripts From f130b2576205452df1f1e6a9331ce294d65d4ab7 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Fri, 21 Jan 2022 14:10:04 +0530 Subject: [PATCH 44/68] remove logic for on the fly template convert + update k8s test --- debian/control | 2 +- engine/schema/pom.xml | 52 +++++++++---------- .../upgrade/SystemVmTemplateRegistration.java | 18 ------- packaging/centos7/cloud.spec | 1 - packaging/centos8/cloud.spec | 1 - packaging/suse15/cloud.spec | 1 - .../systemd/cloudstack-management.service | 1 - .../smoke/test_kubernetes_clusters.py | 20 +++---- .../scripts/configure_systemvm_services.sh | 2 +- 9 files changed, 38 insertions(+), 60 deletions(-) diff --git a/debian/control b/debian/control index 06edfa3c5cac..066994785b38 100644 --- a/debian/control +++ b/debian/control @@ -15,7 +15,7 @@ Description: A common package which contains files which are shared by several C Package: cloudstack-management Architecture: all -Depends: ${python3:Depends}, openjdk-11-jre-headless | java11-runtime-headless | java11-runtime | openjdk-11-jre-headless | zulu-11, cloudstack-common (= ${source:Version}), net-tools, sudo, python3-mysql.connector, augeas-tools, mysql-client | mariadb-client, adduser, bzip2, ipmitool, file, gawk, iproute2, qemu-utils, python3-dnspython, lsb-release, init-system-helpers (>= 1.14~), python3-setuptools, libguestfs-tools +Depends: ${python3:Depends}, openjdk-11-jre-headless | java11-runtime-headless | java11-runtime | openjdk-11-jre-headless | zulu-11, cloudstack-common (= ${source:Version}), net-tools, sudo, python3-mysql.connector, augeas-tools, mysql-client | mariadb-client, adduser, bzip2, ipmitool, file, gawk, iproute2, qemu-utils, python3-dnspython, lsb-release, init-system-helpers (>= 1.14~), python3-setuptools Conflicts: cloud-server, cloud-client, cloud-client-ui Description: CloudStack server library The CloudStack management server diff --git a/engine/schema/pom.xml b/engine/schema/pom.xml index 1258289db98b..4cf0f4328d57 100644 --- a/engine/schema/pom.xml +++ b/engine/schema/pom.xml @@ -188,32 +188,32 @@ ${kvm.checksum} - - - - - - - - - - - - - - - - - - - - - - - - - - + + download-vmware-template + + wget + + + true + + http://10.0.3.122/systemvmtemplate/custom/cks-debian/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-vmware.ova + ${basedir}/dist/systemvm-templates/ + ${vmware.checksum} + + + + download-xenserver-template + + wget + + + true + + http://10.0.3.122/systemvmtemplate/custom/cks-debian/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-xen.vhd.bz2 + ${basedir}/dist/systemvm-templates/ + ${xen.checksum} + + diff --git a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java index 2df2de44995e..214243886997 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java @@ -93,7 +93,6 @@ public class SystemVmTemplateRegistration { public static final String TEMPORARY_SECONDARY_STORE = "tmp"; private static final String PARTIAL_TEMPLATE_FOLDER = String.format("/template/tmpl/%d/", Account.ACCOUNT_ID_SYSTEM); private static final String storageScriptsDir = "scripts/storage/secondary"; - private static final String installerScriptsDir = "scripts/installer/"; private static final Integer OTHER_LINUX_ID = 99; private static final Integer LINUX_5_ID = 15; private static final Integer LINUX_7_ID = 183; @@ -725,7 +724,6 @@ private void validateTemplates(Set hypervisorsInUse) } boolean templatesFound = true; - int count = hypervisors.size(); for (String hypervisor : hypervisors) { String matchedTemplate = templates.stream().filter(x -> x.contains(hypervisor)).findAny().orElse(null); if (matchedTemplate == null) { @@ -734,22 +732,6 @@ private void validateTemplates(Set hypervisorsInUse) } File tempFile = new File(TEMPLATES_PATH + matchedTemplate); - if (!tempFile.exists()) { - --count; - String exportTmpltScript = Script.findScript(installerScriptsDir, "export-templates.sh"); - if (exportTmpltScript == null) { - throw new CloudRuntimeException("Unable to find the export-templates.sh script to export templates on the fly"); - } - Script scr = new Script(exportTmpltScript, SCRIPT_TIMEOUT, LOGGER); - scr.add(hypervisor.toLowerCase(Locale.ROOT)); - scr.add((count > 0 ? "1" : "0")); - String result = scr.execute(); - if (result != null) { - String errMsg = String.format("failed to create template: %s ", result); - LOGGER.error(errMsg); - throw new CloudRuntimeException(errMsg); - } - } String templateChecksum = DigestHelper.calculateChecksum(tempFile); if (!templateChecksum.equals(NewTemplateChecksum.get(getHypervisorType(hypervisor)))) { LOGGER.error(String.format("Checksum mismatch: %s != %s ", templateChecksum, NewTemplateChecksum.get(getHypervisorType(hypervisor)))); diff --git a/packaging/centos7/cloud.spec b/packaging/centos7/cloud.spec index b2f77c5a83b2..81ee8a77a82f 100644 --- a/packaging/centos7/cloud.spec +++ b/packaging/centos7/cloud.spec @@ -79,7 +79,6 @@ Requires: /sbin/service Requires: /sbin/chkconfig Requires: /usr/bin/ssh-keygen Requires: genisoimage -Requires: libguestfs-tools Requires: ipmitool Requires: %{name}-common = %{_ver} Requires: iptables-services diff --git a/packaging/centos8/cloud.spec b/packaging/centos8/cloud.spec index 6a3627a57771..1a946ba0dd95 100644 --- a/packaging/centos8/cloud.spec +++ b/packaging/centos8/cloud.spec @@ -74,7 +74,6 @@ Requires: /sbin/service Requires: /sbin/chkconfig Requires: /usr/bin/ssh-keygen Requires: genisoimage -Requires: libguestfs-tools Requires: ipmitool Requires: %{name}-common = %{_ver} Requires: iptables-services diff --git a/packaging/suse15/cloud.spec b/packaging/suse15/cloud.spec index 77b6f6e95ac4..f355640c8650 100644 --- a/packaging/suse15/cloud.spec +++ b/packaging/suse15/cloud.spec @@ -75,7 +75,6 @@ Requires: /sbin/service Requires: /sbin/chkconfig Requires: /usr/bin/ssh-keygen Requires: mkisofs -Requires: libguestfs-tools Requires: ipmitool Requires: %{name}-common = %{_ver} Requires: qemu-tools diff --git a/packaging/systemd/cloudstack-management.service b/packaging/systemd/cloudstack-management.service index db94a42d6439..b979f7f375a7 100644 --- a/packaging/systemd/cloudstack-management.service +++ b/packaging/systemd/cloudstack-management.service @@ -35,7 +35,6 @@ EnvironmentFile=/etc/default/cloudstack-management WorkingDirectory=/var/log/cloudstack/management PIDFile=/var/run/cloudstack-management.pid ExecStart=/usr/bin/java $JAVA_DEBUG $JAVA_OPTS -cp $CLASSPATH $BOOTSTRAP_CLASS -TimeoutSec=900 [Install] WantedBy=multi-user.target diff --git a/test/integration/smoke/test_kubernetes_clusters.py b/test/integration/smoke/test_kubernetes_clusters.py index 0387ddf9cc1b..46f1f5d02bdc 100644 --- a/test/integration/smoke/test_kubernetes_clusters.py +++ b/test/integration/smoke/test_kubernetes_clusters.py @@ -101,12 +101,12 @@ def setUpClass(cls): (cls.services["cks_kubernetes_versions"]["1.20.9"]["semanticversion"], cls.services["cks_kubernetes_versions"]["1.20.9"]["url"], e)) if cls.setup_failed == False: try: - cls.kubernetes_version_1_21_3 = cls.addKubernetesSupportedVersion(cls.services["cks_kubernetes_versions"]["1.21.3"]) - cls.kubernetes_version_ids.append(cls.kubernetes_version_1_21_3.id) + cls.kubernetes_version_1_21_5 = cls.addKubernetesSupportedVersion(cls.services["cks_kubernetes_versions"]["1.21.5"]) + cls.kubernetes_version_ids.append(cls.kubernetes_version_1_21_5.id) except Exception as e: cls.setup_failed = True cls.debug("Failed to get Kubernetes version ISO in ready state, version=%s, url=%s, %s" % - (cls.services["cks_kubernetes_versions"]["1.21.3"]["semanticversion"], cls.services["cks_kubernetes_versions"]["1.21.3"]["url"], e)) + (cls.services["cks_kubernetes_versions"]["1.21.5"]["semanticversion"], cls.services["cks_kubernetes_versions"]["1.21.5"]["url"], e)) if cls.setup_failed == False: cks_offering_data = cls.services["cks_service_offering"] @@ -349,7 +349,7 @@ def test_01_invalid_upgrade_kubernetes_cluster(self): if self.setup_failed == True: self.fail("Setup incomplete") global k8s_cluster - k8s_cluster = self.getValidKubernetesCluster(version=self.kubernetes_version_1_21_3) + k8s_cluster = self.getValidKubernetesCluster(version=self.kubernetes_version_1_21_5) self.debug("Downgrading Kubernetes cluster with ID: %s to a lower version. This should fail!" % k8s_cluster.id) @@ -362,7 +362,7 @@ def test_01_invalid_upgrade_kubernetes_cluster(self): self.debug("Upgrading Kubernetes cluster with invalid Kubernetes supported version check successful, API failure: %s" % e) self.deleteKubernetesClusterAndVerify(k8s_cluster.id, False, True) - self.verifyKubernetesClusterUpgrade(k8s_cluster, self.kubernetes_version_1_21_3.id) + self.verifyKubernetesClusterUpgrade(k8s_cluster, self.kubernetes_version_1_21_5.id) return @attr(tags=["advanced", "smoke"], required_hardware="true") @@ -381,12 +381,12 @@ def test_02_upgrade_kubernetes_cluster(self): time.sleep(self.services["sleep"]) self.debug("Upgrading Kubernetes cluster with ID: %s" % k8s_cluster.id) try: - k8s_cluster = self.upgradeKubernetesCluster(k8s_cluster.id, self.kubernetes_version_1_21_3.id) + k8s_cluster = self.upgradeKubernetesCluster(k8s_cluster.id, self.kubernetes_version_1_21_5.id) except Exception as e: self.deleteKubernetesClusterAndVerify(k8s_cluster.id, False, True) self.fail("Failed to upgrade Kubernetes cluster due to: %s" % e) - self.verifyKubernetesClusterUpgrade(k8s_cluster, self.kubernetes_version_1_21_3.id) + self.verifyKubernetesClusterUpgrade(k8s_cluster, self.kubernetes_version_1_21_5.id) return @attr(tags=["advanced", "smoke"], required_hardware="true") @@ -434,7 +434,7 @@ def test_04_autoscale_kubernetes_cluster(self): if self.setup_failed == True: self.fail("Setup incomplete") global k8s_cluster - k8s_cluster = self.getValidKubernetesCluster(version=self.kubernetes_version_1_21_3) + k8s_cluster = self.getValidKubernetesCluster(version=self.kubernetes_version_1_21_5) self.debug("Autoscaling Kubernetes cluster with ID: %s" % k8s_cluster.id) try: @@ -535,12 +535,12 @@ def test_08_upgrade_kubernetes_ha_cluster(self): self.debug("Upgrading HA Kubernetes cluster with ID: %s" % k8s_cluster.id) try: - k8s_cluster = self.upgradeKubernetesCluster(k8s_cluster.id, self.kubernetes_version_1_21_3.id) + k8s_cluster = self.upgradeKubernetesCluster(k8s_cluster.id, self.kubernetes_version_1_21_5.id) except Exception as e: self.deleteKubernetesClusterAndVerify(k8s_cluster.id, False, True) self.fail("Failed to upgrade Kubernetes HA cluster due to: %s" % e) - self.verifyKubernetesClusterUpgrade(k8s_cluster, self.kubernetes_version_1_21_3.id) + self.verifyKubernetesClusterUpgrade(k8s_cluster, self.kubernetes_version_1_21_5.id) self.debug("Kubernetes cluster with ID: %s successfully upgraded" % k8s_cluster.id) return diff --git a/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh b/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh index 36b324a314f8..115d340fe846 100644 --- a/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh +++ b/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh @@ -19,7 +19,7 @@ set -e set -x -CLOUDSTACK_RELEASE=4.16.0 +CLOUDSTACK_RELEASE=4.17.0 function configure_apache2() { # Enable ssl, rewrite and auth From 8937867ed91e5471f83b63ac4f0daf42f90206aa Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Sat, 22 Jan 2022 12:51:30 +0530 Subject: [PATCH 45/68] fix syntax issue - causing issue with shared network tests --- systemvm/debian/opt/cloud/bin/setup/init.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/systemvm/debian/opt/cloud/bin/setup/init.sh b/systemvm/debian/opt/cloud/bin/setup/init.sh index 5923b351d1c2..a1ac48e46b56 100644 --- a/systemvm/debian/opt/cloud/bin/setup/init.sh +++ b/systemvm/debian/opt/cloud/bin/setup/init.sh @@ -190,7 +190,7 @@ setup_interface_sshd() { setup_common eth0 eth1 setup_sshd $ETH1_IP "eth1" - elif [ "$TYPE" == "elbvm" ] || [ "$TYPE" == "dhcpsrvr"]; then + elif [ "$TYPE" == "elbvm" ] || [ "$TYPE" == "dhcpsrvr" ]; then setup_common eth0 eth1 if [ "$SSHONGUEST" == "true" ]; then setup_sshd $ETH0_IP "eth0" From d306404cb1f1e34bc85811c88edf27de150e213b Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Thu, 27 Jan 2022 12:48:03 +0530 Subject: [PATCH 46/68] Code cleanup --- .../com/cloud/agent/api/StartCommand.java | 30 ------------------- .../VirtualRoutingResource.java | 22 ++++++++++++-- .../com/cloud/resource/ServerResource.java | 3 +- .../cloud/vm/VirtualMachineManagerImpl.java | 13 -------- .../LibvirtPatchSystemVmCommandWrapper.java | 2 +- .../wrapper/LibvirtStartCommandWrapper.java | 4 +-- .../vmware/resource/VmwareResource.java | 6 ++-- .../resource/CitrixResourceBase.java | 2 +- .../xenbase/CitrixStartCommandWrapper.java | 2 -- .../opt/cloud/bin/setup/cloud-early-config | 3 -- systemvm/patch-sysvms.sh | 3 +- 11 files changed, 26 insertions(+), 64 deletions(-) diff --git a/core/src/main/java/com/cloud/agent/api/StartCommand.java b/core/src/main/java/com/cloud/agent/api/StartCommand.java index 3af11932588e..24b0ac3787b5 100644 --- a/core/src/main/java/com/cloud/agent/api/StartCommand.java +++ b/core/src/main/java/com/cloud/agent/api/StartCommand.java @@ -29,12 +29,6 @@ public class StartCommand extends Command { String hostIp; boolean executeInSequence = false; String secondaryStorage; - @LogLevel(LogLevel.Log4jLevel.Off) - private String certificate; - @LogLevel(LogLevel.Log4jLevel.Off) - private String privateKey = ""; - @LogLevel(LogLevel.Log4jLevel.Off) - private String caCertificates; public VirtualMachineTO getVirtualMachine() { return vm; @@ -70,28 +64,4 @@ public String getSecondaryStorage() { public void setSecondaryStorage(String secondary) { this.secondaryStorage = secondary; } - - public void setCertificate(String certificate) { - this.certificate = certificate; - } - - public void setPrivateKey(String privateKey) { - this.privateKey = privateKey; - } - - public void setCaCertificates(String caCertificates) { - this.caCertificates = caCertificates; - } - - public String getCertificate() { - return certificate; - } - - public String getPrivateKey() { - return privateKey; - } - - public String getCaCertificates() { - return caCertificates; - } } diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java index cddee33ac382..ee85f3681f83 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java @@ -174,12 +174,28 @@ private Answer execute(final SetupKeyStoreCommand cmd) { return new SetupKeystoreAnswer(result.getDetails()); } + private void scpCertificateFiles(String routerIp, String path, String filename, String content) throws InterruptedException { + String errMsg = "Failed to scp file: %s to system VM"; + for (int retries = 5; retries > 0; retries--) { + try { + _vrDeployer.createFileInVR(routerIp, path, filename, content); + } catch (Exception e) { + errMsg += ", retrying"; + s_logger.error(String.format(errMsg, filename), e); + Thread.sleep(2000); + } + } + } private Answer execute(final SetupCertificateCommand cmd) { String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); if (!org.apache.commons.lang3.StringUtils.isEmpty(routerName) && (routerName.startsWith("s-") || routerName.startsWith("v-"))) { - _vrDeployer.createFileInVR(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.CERT_FILENAME, cmd.getCertificate()); - _vrDeployer.createFileInVR(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.CACERT_FILENAME, cmd.getCaCertificates()); - _vrDeployer.createFileInVR(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.PKEY_FILENAME, cmd.getPrivateKey()); + try { + scpCertificateFiles(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.CERT_FILENAME, cmd.getCertificate()); + scpCertificateFiles(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.CACERT_FILENAME, cmd.getCaCertificates()); + scpCertificateFiles(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.PKEY_FILENAME, cmd.getPrivateKey()); + } catch (InterruptedException e) { + throw new CloudRuntimeException(String.format("Failed to scp certificate file to %s due to %s", routerName, e.getLocalizedMessage())); + } } final String args = String.format("/usr/local/cloud/systemvm/conf/agent.properties %s " + "/usr/local/cloud/systemvm/conf/%s %s " + diff --git a/core/src/main/java/com/cloud/resource/ServerResource.java b/core/src/main/java/com/cloud/resource/ServerResource.java index f2beb4a1845a..0afb040b249f 100644 --- a/core/src/main/java/com/cloud/resource/ServerResource.java +++ b/core/src/main/java/com/cloud/resource/ServerResource.java @@ -35,8 +35,7 @@ */ public interface ServerResource extends Manager { - String[] srcFiles = new String[] { "agent.zip", "cloud-scripts.tgz" }; - String[] newSrcFiles = new String[] { "agent.zip", "cloud-scripts.tgz", "patch-sysvms.sh" }; + String[] systemVmPatchFiles = new String[] { "agent.zip", "cloud-scripts.tgz", "patch-sysvms.sh" }; String[] certificateFiles = new String[] {KeyStoreUtils.CERT_FILENAME, KeyStoreUtils.CACERT_FILENAME, KeyStoreUtils.PKEY_FILENAME}; String SSHKEYSPATH = "/root/.ssh"; diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index 2a9438198749..12032dba054c 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -17,7 +17,6 @@ package com.cloud.vm; -import java.io.IOException; import java.net.URI; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -80,7 +79,6 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.cloudstack.utils.identity.ManagementServerNode; -import org.apache.cloudstack.utils.security.CertUtils; import org.apache.cloudstack.vm.UnmanagedVMsManager; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; @@ -1198,17 +1196,6 @@ public void orchestrateStart(final String vmUuid, final Map(ipAddressDetails.values()), CAManager.CertValidityPeriod.value(), null); - try { - command.setCertificate(CertUtils.x509CertificateToPem(certificate.getClientCertificate())); - command.setCaCertificates(CertUtils.x509CertificatesToPem(certificate.getCaCertificates())); - command.setPrivateKey(CertUtils.privateKeyToPem(certificate.getPrivateKey())); - } catch (IOException e) { - throw new CloudRuntimeException("Failed to generate/setup certificates for system VM"); - } - } cmds.addCommand(command); vmGuru.finalizeDeployment(cmds, vmProfile, dest, ctx); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java index 38b505f561ac..8d4700bf5694 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java @@ -70,7 +70,7 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR Pair patchResult = null; try { - FileUtil.scpPatchFiles(controlIp, "/home/cloud", sshPort, pemFile, serverResource.newSrcFiles, LibvirtComputingResource.BASEPATH); + FileUtil.scpPatchFiles(controlIp, "/home/cloud", sshPort, pemFile, serverResource.systemVmPatchFiles, LibvirtComputingResource.BASEPATH); patchResult = SshHelper.sshExecute(controlIp, sshPort, "root", pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 600000); } catch (Exception e) { diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java index 1f6a0256cc83..b8c2e447ae2a 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java @@ -120,9 +120,7 @@ public Answer execute(final StartCommand command, final LibvirtComputingResource try { File pemFile = new File(LibvirtComputingResource.SSHPRVKEYPATH); - FileUtil.scpPatchFiles(controlIp, "/home/cloud", Integer.parseInt(LibvirtComputingResource.DEFAULTDOMRSSHPORT), pemFile, LibvirtComputingResource.newSrcFiles, LibvirtComputingResource.BASEPATH); - // TODO: May want to remove this when cert patching logic is moved - Thread.sleep(10000); + FileUtil.scpPatchFiles(controlIp, "/home/cloud", Integer.parseInt(LibvirtComputingResource.DEFAULTDOMRSSHPORT), pemFile, LibvirtComputingResource.systemVmPatchFiles, LibvirtComputingResource.BASEPATH); } catch (Exception e) { String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; s_logger.error(errMsg, e); diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 476734284749..6891bfd19320 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -662,7 +662,7 @@ private Answer execute(PatchSystemVmCommand cmd) { ExecutionResult result = getSystemVmVersionAndChecksum(controlIp); try { - FileUtil.scpPatchFiles(controlIp, "/home/cloud", DefaultDomRSshPort, pemFile, newSrcFiles, BASEPATH); + FileUtil.scpPatchFiles(controlIp, "/home/cloud", DefaultDomRSshPort, pemFile, systemVmPatchFiles, BASEPATH); } catch (CloudRuntimeException e) { return new PatchSystemVmAnswer(cmd, e.getMessage()); } @@ -2549,9 +2549,7 @@ protected StartAnswer execute(StartCommand cmd) { try { String homeDir = System.getProperty("user.home"); File pemFile = new File(homeDir + "/.ssh/id_rsa"); - FileUtil.scpPatchFiles(controlIp, "/home/cloud", DefaultDomRSshPort, pemFile, newSrcFiles, BASEPATH); - // TODO: May want to remove this when cert patching logic is moved - Thread.sleep(10000); + FileUtil.scpPatchFiles(controlIp, "/home/cloud", DefaultDomRSshPort, pemFile, systemVmPatchFiles, BASEPATH); } catch (Exception e) { String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; s_logger.error(errMsg, e); diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java index 1e9b0388883f..0b024c010166 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java @@ -999,7 +999,7 @@ public ExecutionResult copyPatchFilesToVR(final String routerIp, final String pa final Connection conn = getConnection(); final String hostPath = "/opt/xensource/packages/resources/"; String rc = ""; - for (String file: newSrcFiles) { + for (String file: systemVmPatchFiles) { rc = callHostPlugin(conn, "vmops", "createFileInDomr", "domrip", routerIp, "srcfilepath", hostPath.concat(file), "dstfilepath", path, "cleanup", "false"); if (rc.startsWith("fail#")) { s_logger.error(String.format("Failed to scp file %s required for patching the systemVM", file)); diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java index f4ee77c347f3..73a74f89d5dd 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java @@ -196,8 +196,6 @@ public Answer execute(final StartCommand command, final CitrixResourceBase citri try { citrixResourceBase.copyPatchFilesToVR(controlIp, "/home/cloud"); - // TODO: May want to remove this when cert patching logic is moved - Thread.sleep(10000); } catch (Exception e) { String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; s_logger.error(errMsg, e); diff --git a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config index 13fa9987a5e7..1227c68850b9 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config +++ b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config @@ -100,9 +100,6 @@ patch() { cleanup() { rm -rf /home/cloud/agent.zip mv /home/cloud/cloud-scripts.tgz /usr/share/cloud/cloud-scripts.tgz - if [ -f /home/cloud/cloud.crt ]; then - mv /home/cloud/cloud.crt /home/cloud/cloud.ca.crt /home/cloud/cloud.key /usr/local/cloud/systemvm/conf/ - fi } start() { diff --git a/systemvm/patch-sysvms.sh b/systemvm/patch-sysvms.sh index 148c8a80b9da..4a6873147b8f 100644 --- a/systemvm/patch-sysvms.sh +++ b/systemvm/patch-sysvms.sh @@ -74,7 +74,6 @@ restart_services() { systemctl is-active --quiet "$svc" if [ $? -eq 0 ]; then systemctl restart "$svc" - sleep 5 systemctl is-active --quiet "$svc" if [ $? -gt 0 ]; then echo "Failed to start "$svc" service. Patch Failed. Retrying again" >> $logfile 2>&1 @@ -100,10 +99,10 @@ cleanup_systemVM() { patch_systemvm() { rm -rf /usr/local/cloud/systemvm - mkdir -p /usr/local/cloud/systemvm if [ "$TYPE" == "consoleproxy" ] || [ "$TYPE" == "secstorage" ]; then echo "All" | unzip $newpath/agent.zip -d /usr/local/cloud/systemvm >> $logfile 2>&1 + mkdir -p /usr/local/cloud/systemvm find /usr/local/cloud/systemvm/ -name \*.sh | xargs chmod 555 fi echo "Extracting cloud scripts" >> $logfile 2>&1 From 420f54a6a1c9aa1277c4ad3af0b5482c8d405be2 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Wed, 9 Feb 2022 17:55:57 +0530 Subject: [PATCH 47/68] add cgroup config for containerd --- .../src/main/resources/conf/k8s-control-node-add.yml | 1 + .../src/main/resources/conf/k8s-control-node.yml | 1 + .../kubernetes-service/src/main/resources/conf/k8s-node.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml index 480e7bba8526..a92f1039eaee 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml @@ -260,6 +260,7 @@ write_files: runcmd: - chown -R cloud:cloud /home/cloud/.ssh - containerd config default > /etc/containerd/config.toml + - sed -i '/\[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options\]/a '"\\ SystemdCgroup=true"'' /etc/containerd/config.toml - systemctl restart containerd - [ systemctl, start, setup-kube-system ] - [ systemctl, start, deploy-kube-system ] diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml index ceca597516fa..8662dcf8d1bd 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml @@ -317,6 +317,7 @@ write_files: runcmd: - chown -R cloud:cloud /home/cloud/.ssh - containerd config default > /etc/containerd/config.toml + - sed -i '/\[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options\]/a '"\\ SystemdCgroup=true"'' /etc/containerd/config.toml - systemctl restart containerd - [ systemctl, start, setup-kube-system ] - [ systemctl, start, deploy-kube-system ] diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml index b6a71e8deb2e..03405d32fc83 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml @@ -260,6 +260,7 @@ write_files: runcmd: - chown -R cloud:cloud /home/cloud/.ssh - containerd config default > /etc/containerd/config.toml + - sed -i '/\[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options\]/a '"\\ SystemdCgroup=true"'' /etc/containerd/config.toml - systemctl restart containerd - [ systemctl, start, setup-kube-system ] - [ systemctl, start, deploy-kube-system ] From 62c274f1a72823571b24931a5d5a83ed1e8a10c3 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Thu, 10 Feb 2022 18:05:15 +0530 Subject: [PATCH 48/68] add systemd config for kubelet --- .../src/main/resources/conf/k8s-control-node-add.yml | 2 ++ .../src/main/resources/conf/k8s-control-node.yml | 2 ++ .../kubernetes-service/src/main/resources/conf/k8s-node.yml | 2 ++ 3 files changed, 6 insertions(+) diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml index a92f1039eaee..4ded4ff7f4a9 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml @@ -107,6 +107,8 @@ write_files: mkdir -p /etc/systemd/system/kubelet.service.d sed "s:/usr/bin:/opt/bin:g" ${BINARIES_DIR}/10-kubeadm.conf > /etc/systemd/system/kubelet.service.d/10-kubeadm.conf + echo "KUBELET_EXTRA_ARGS=--cgroup-driver=systemd" > /etc/default/kubelet + output=`ls ${BINARIES_DIR}/docker/` if [ "$output" != "" ]; then while read -r line; do diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml index 8662dcf8d1bd..bde7996ec627 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml @@ -127,6 +127,8 @@ write_files: mkdir -p /etc/systemd/system/kubelet.service.d sed "s:/usr/bin:/opt/bin:g" ${BINARIES_DIR}/10-kubeadm.conf > /etc/systemd/system/kubelet.service.d/10-kubeadm.conf + echo "KUBELET_EXTRA_ARGS=--cgroup-driver=systemd" > /etc/default/kubelet + output=`ls ${BINARIES_DIR}/docker/` if [ "$output" != "" ]; then while read -r line; do diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml index 03405d32fc83..87b38459c2eb 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml @@ -107,6 +107,8 @@ write_files: mkdir -p /etc/systemd/system/kubelet.service.d sed "s:/usr/bin:/opt/bin:g" ${BINARIES_DIR}/10-kubeadm.conf > /etc/systemd/system/kubelet.service.d/10-kubeadm.conf + echo "KUBELET_EXTRA_ARGS=--cgroup-driver=systemd" > /etc/default/kubelet + output=`ls ${BINARIES_DIR}/docker/` if [ "$output" != "" ]; then while read -r line; do From 79792e37613dd8a882064713b01b03ea6a50a3dc Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Fri, 11 Feb 2022 18:14:34 +0530 Subject: [PATCH 49/68] add additional info during image registry config --- .../KubernetesClusterResourceModifierActionWorker.java | 4 ++++ .../src/main/resources/conf/k8s-control-node-add.yml | 2 +- .../src/main/resources/conf/k8s-control-node.yml | 4 ++-- .../kubernetes-service/src/main/resources/conf/k8s-node.yml | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java index dfa5d4e48e21..37563c922b85 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java @@ -198,11 +198,15 @@ protected String updateKubeConfigWithRegistryDetails(String k8sConfig) { final String registryUrlKey = "{{registry.url}}"; final String registryUrlEpKey = "{{registry.url.endpoint}}"; final String registryAuthKey = "{{registry.token}}"; + final String registryUname = "{{registry.username}}"; + final String registryPsswd = "{{registry.password}}"; final String usernamePasswordKey = registryUsername + ":" + registryPassword; String base64Auth = Base64.encodeBase64String(usernamePasswordKey.getBytes((com.cloud.utils.StringUtils.getPreferredCharset()))); k8sConfig = k8sConfig.replace(registryUrlKey, registryUrl); k8sConfig = k8sConfig.replace(registryUrlEpKey, registryEp); + k8sConfig = k8sConfig.replace(registryUname, registryUsername); + k8sConfig = k8sConfig.replace(registryPsswd, registryPassword); k8sConfig = k8sConfig.replace(registryAuthKey, base64Auth); } return k8sConfig; diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml index 4ded4ff7f4a9..3156f378674e 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml @@ -222,7 +222,7 @@ write_files: #!/bin/bash -e export registryConfig="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.mirrors.\"{{registry.url.endpoint}}\"]\n \\ endpoint = [\"{{registry.url}}\"]" - export registryCredentials="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.configs.\"{{registry.url}}\".auth]\n \tauth = \"\" \n \tidentitytoken = \"{{registry.token}}\"" + export registryCredentials="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.configs.\"{{registry.url.endpoint}}\".auth]\n\tusername = \"{{registry.username}}\" \n\tpassword = \"{{registry.password}}\" \n\tidentitytoken = \"{{registry.token}}\"" echo "creating config file for containerd" containerd config default > /etc/containerd/config.toml diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml index bde7996ec627..6c9b92108170 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml @@ -279,8 +279,8 @@ write_files: #!/bin/bash -e export registryConfig="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.mirrors.\"{{registry.url.endpoint}}\"]\n \\ endpoint = [\"{{registry.url}}\"]" - export registryCredentials="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.configs.\"{{registry.url.endpoint}}\".auth]\n \tauth = \"\" \n \tidentitytoken = \"{{registry.token}}\"" - + export registryCredentials="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.configs.\"{{registry.url.endpoint}}\".auth]\n\tusername = \"{{registry.username}}\" \n\tpassword = \"{{registry.password}}\" \n\tidentitytoken = \"{{registry.token}}\"" + echo "creating config file for containerd" containerd config default > /etc/containerd/config.toml sed -i '/\[plugins."io.containerd.grpc.v1.cri".registry\]/a '"${registryCredentials}"'' /etc/containerd/config.toml diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml index 87b38459c2eb..eedc1d0c8c88 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml @@ -222,7 +222,7 @@ write_files: #!/bin/bash -e export registryConfig="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.mirrors.\"{{registry.url.endpoint}}\"]\n \\ endpoint = [\"{{registry.url}}\"]" - export registryCredentials="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.configs.\"{{registry.url}}\".auth]\n \tauth = \"\" \n \tidentitytoken = \"{{registry.token}}\"" + export registryCredentials="\\ [plugins.\"io.containerd.grpc.v1.cri\".registry.configs.\"{{registry.url.endpoint}}\".auth]\n\tusername = \"{{registry.username}}\" \n\tpassword = \"{{registry.password}}\" \n\tidentitytoken = \"{{registry.token}}\"" echo "creating config file for containerd" containerd config default > /etc/containerd/config.toml From e42b5cf1f8799eb7579a53b8f4bc0c2f15dcbc85 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Mon, 14 Feb 2022 14:10:22 +0530 Subject: [PATCH 50/68] address comments --- .../api/command/admin/systemvm/PatchSystemVMCmd.java | 7 ++++--- .../com/cloud/upgrade/SystemVmTemplateRegistration.java | 4 ++-- systemvm/debian/opt/cloud/bin/setup/dhcpsrvr.sh | 7 ------- systemvm/debian/opt/cloud/bin/setup/ilbvm.sh | 1 - systemvm/debian/opt/cloud/bin/setup/vpcrouter.sh | 1 - utils/src/main/java/com/cloud/utils/FileUtil.java | 2 +- .../org/apache/cloudstack/utils/security/DigestHelper.java | 2 +- 7 files changed, 8 insertions(+), 16 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java index 0f08ad7f0a20..dd44245f6c67 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java @@ -25,6 +25,7 @@ import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.SuccessResponse; @@ -32,12 +33,12 @@ import org.apache.cloudstack.context.CallContext; import org.apache.log4j.Logger; -@APICommand(name = "patchSystemVm", description = "Attempts to live patch systemVMs - CPVM, SSVM, Routers ", +@APICommand(name = PatchSystemVMCmd.APINAME, description = "Attempts to live patch systemVMs - CPVM, SSVM ", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = { RoleType.Admin }) public class PatchSystemVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(PatchSystemVMCmd.class.getName()); - private static final String s_name = "patchsystemvmresponse"; + public static final String APINAME = "PatchSystemVM"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -80,7 +81,7 @@ public String getEventDescription() { @Override public String getCommandName() { - return s_name; + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; } @Override diff --git a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java index 78afe3a45c02..9bb81f08cdc8 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/SystemVmTemplateRegistration.java @@ -681,8 +681,8 @@ public void registerTemplate(Pair hypervisorA /** * This method parses the metadata file consisting of the systemVM templates information - * @return the version of the systemvm template that is to be used. This is done to in order - * to fallback on the latest available version of the systemVM template when there does not + * @return the version of the systemvm template that is to be used. This is done in order + * to fallback on the latest available version of the systemVM template when there doesn't * exist a template corresponding to the current code version. */ public static String parseMetadataFile() { diff --git a/systemvm/debian/opt/cloud/bin/setup/dhcpsrvr.sh b/systemvm/debian/opt/cloud/bin/setup/dhcpsrvr.sh index 0b9e8a7c5cc6..27dbf3e8f628 100755 --- a/systemvm/debian/opt/cloud/bin/setup/dhcpsrvr.sh +++ b/systemvm/debian/opt/cloud/bin/setup/dhcpsrvr.sh @@ -25,7 +25,6 @@ dhcpsrvr_svcs() { setup_dhcpsrvr() { log_it "Setting up dhcp server system vm" -# setup_common eth0 eth1 setup_dnsmasq setup_apache2 $ETH0_IP @@ -40,12 +39,6 @@ setup_dhcpsrvr() { sed -i "s/-A INPUT -i eth0 -p udp -m udp --dport 53 -j ACCEPT/-A INPUT -i eth0 -p udp -m udp --dport 53 -s $DHCP_RANGE\/$CIDR_SIZE -j ACCEPT/g" /etc/iptables/rules.v4 sed -i "s/-A INPUT -i eth0 -p tcp -m tcp --dport 53 -j ACCEPT/-A INPUT -i eth0 -p tcp -m tcp --dport 53 -s $DHCP_RANGE\/$CIDR_SIZE -j ACCEPT/g" /etc/iptables/rules.v4 -# if [ "$SSHONGUEST" == "true" ] -# then -# setup_sshd $ETH0_IP "eth0" -# else -# setup_sshd $ETH1_IP "eth1" -# fi } dhcpsrvr_svcs diff --git a/systemvm/debian/opt/cloud/bin/setup/ilbvm.sh b/systemvm/debian/opt/cloud/bin/setup/ilbvm.sh index 83cc85525d5a..a130674d1e8a 100755 --- a/systemvm/debian/opt/cloud/bin/setup/ilbvm.sh +++ b/systemvm/debian/opt/cloud/bin/setup/ilbvm.sh @@ -25,7 +25,6 @@ ilbvm_svcs() { setup_ilbvm() { log_it "Setting up Internal Load Balancer system vm" -# setup_common eth0 eth1 #eth0 = guest network, eth1=control network sed -i /$NAME/d /etc/hosts diff --git a/systemvm/debian/opt/cloud/bin/setup/vpcrouter.sh b/systemvm/debian/opt/cloud/bin/setup/vpcrouter.sh index ba4af90d9b6c..bfb062188254 100755 --- a/systemvm/debian/opt/cloud/bin/setup/vpcrouter.sh +++ b/systemvm/debian/opt/cloud/bin/setup/vpcrouter.sh @@ -85,7 +85,6 @@ EOF enable_fwding 1 enable_passive_ftp 1 cp /etc/iptables/iptables-vpcrouter /etc/iptables/rules.v4 -# setup_sshd $ETH0_IP "eth0" cp /etc/vpcdnsmasq.conf /etc/dnsmasq.conf cp /etc/cloud-nic.rules /etc/udev/rules.d/cloud-nic.rules echo "" > /etc/dnsmasq.d/dhcphosts.txt diff --git a/utils/src/main/java/com/cloud/utils/FileUtil.java b/utils/src/main/java/com/cloud/utils/FileUtil.java index cc44c0b80570..3a44127fe140 100644 --- a/utils/src/main/java/com/cloud/utils/FileUtil.java +++ b/utils/src/main/java/com/cloud/utils/FileUtil.java @@ -51,7 +51,7 @@ public static void scpPatchFiles(String controlIp, String destPath, int sshPort, return; } catch (Exception e) { errMsg += ", retrying"; - s_logger.error(errMsg, e); + s_logger.error(errMsg); } } throw new CloudRuntimeException(errMsg); diff --git a/utils/src/main/java/org/apache/cloudstack/utils/security/DigestHelper.java b/utils/src/main/java/org/apache/cloudstack/utils/security/DigestHelper.java index 7e4e80f8f4d2..d480387de7ee 100644 --- a/utils/src/main/java/org/apache/cloudstack/utils/security/DigestHelper.java +++ b/utils/src/main/java/org/apache/cloudstack/utils/security/DigestHelper.java @@ -146,7 +146,7 @@ public static String calculateChecksum(File file) { return DigestUtils.md5Hex(is); } catch (IOException e) { String errMsg = "Failed to calculate template checksum"; - LOGGER.error(errMsg, e); + LOGGER.error(errMsg); throw new CloudRuntimeException(errMsg, e); } } From ed18685e459b9c9460532ac6963f6bee491f1db9 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Mon, 21 Feb 2022 11:50:45 +0530 Subject: [PATCH 51/68] add temp links of download.cloudstack.org --- engine/schema/pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/engine/schema/pom.xml b/engine/schema/pom.xml index 2b259ba7c596..62c2012ffcdd 100644 --- a/engine/schema/pom.xml +++ b/engine/schema/pom.xml @@ -123,7 +123,7 @@ - http://10.0.3.122/systemvmtemplate/custom/cks-debian/${cs.version}/md5sum.txt + https://download.cloudstack.org/testing/systemvmtemplate/${cs.version}/md5sum.txt ${basedir}/dist/systemvm-templates/ true true @@ -183,7 +183,7 @@ true - http://10.0.3.122/systemvmtemplate/custom/cks-debian/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-kvm.qcow2.bz2 + https://download.cloudstack.org/testing/systemvmtemplate/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-kvm.qcow2.bz2 ${basedir}/dist/systemvm-templates/ ${kvm.checksum} @@ -196,7 +196,7 @@ true - http://10.0.3.122/systemvmtemplate/custom/cks-debian/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-vmware.ova + https://download.cloudstack.org/testing/systemvmtemplate/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-vmware.ova ${basedir}/dist/systemvm-templates/ ${vmware.checksum} @@ -209,7 +209,7 @@ true - http://10.0.3.122/systemvmtemplate/custom/cks-debian/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-xen.vhd.bz2 + https://download.cloudstack.org/testing/systemvmtemplate/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-xen.vhd.bz2 ${basedir}/dist/systemvm-templates/ ${xen.checksum} From ff386aced54292f1ee0793ad461f5699f3c8a7a1 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Tue, 22 Feb 2022 12:16:32 +0530 Subject: [PATCH 52/68] address part of the comments --- .../command/admin/systemvm/PatchSystemVMCmd.java | 4 ++-- .../command/user/network/RestartNetworkCmd.java | 4 +++- .../api/command/user/vpc/RestartVPCCmd.java | 4 +++- .../virtualnetwork/VirtualRoutingResource.java | 9 ++++++--- .../java/com/cloud/resource/ServerResource.java | 4 +--- .../kvm/resource/LibvirtComputingResource.java | 2 -- scripts/util/keystore-cert-import | 7 ------- .../consoleproxy/ConsoleProxyManagerImpl.java | 1 - .../java/com/cloud/consoleproxy/ConsoleProxy.java | 14 +++++++------- .../SecondaryStorageManagerImpl.java | 1 - .../etc/systemd/system/cloud-postinit.service | 1 - 11 files changed, 22 insertions(+), 29 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java index dd44245f6c67..ea6240549109 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java @@ -35,10 +35,10 @@ @APICommand(name = PatchSystemVMCmd.APINAME, description = "Attempts to live patch systemVMs - CPVM, SSVM ", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, - responseHasSensitiveInfo = false, authorized = { RoleType.Admin }) + responseHasSensitiveInfo = false, authorized = { RoleType.Admin }, since = "4.17.0") public class PatchSystemVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(PatchSystemVMCmd.class.getName()); - public static final String APINAME = "PatchSystemVM"; + public static final String APINAME = "patchSystemVm"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java index 52d659e1449d..d0ef279aeced 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java @@ -59,7 +59,9 @@ public class RestartNetworkCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.MAKEREDUNDANT, type = CommandType.BOOLEAN, required = false, description = "Turn the network into a network with redundant routers.", since = "4.11.1") private Boolean makeRedundant = false; - @Parameter(name = ApiConstants.LIVE_PATCH, type = CommandType.BOOLEAN, required = false, description = "Live Patch the router before restarting it. This parameter will work only when 'cleanup' is false.", since = "4.16.1") + @Parameter(name = ApiConstants.LIVE_PATCH, type = CommandType.BOOLEAN, required = false, + description = "Live patches the router software before restarting it. This parameter will only work when 'cleanup' is false.", + since = "4.17.0") private Boolean livePatch = false; ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java index 0e9689816471..ac22e6691595 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java @@ -54,7 +54,9 @@ public class RestartVPCCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.MAKEREDUNDANT, type = CommandType.BOOLEAN, required = false, description = "Turn a single VPC into a redundant one.") private Boolean makeredundant = false; - @Parameter(name = ApiConstants.LIVE_PATCH, type = CommandType.BOOLEAN, required = false, description = "Live Patch the router before restarting it", since = "4.16.1") + @Parameter(name = ApiConstants.LIVE_PATCH, type = CommandType.BOOLEAN, required = false, + description = "Live patches the router software before restarting it. This parameter will only work when 'cleanup' is false.", + since = "4.17.0") private Boolean livePatch = false; ///////////////////////////////////////////////////// diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java index 0057da6cd2f4..3fe8470c0b69 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java @@ -174,11 +174,14 @@ private Answer execute(final SetupKeyStoreCommand cmd) { return new SetupKeystoreAnswer(result.getDetails()); } - private void scpFileToIdentifyPatching(String routerIp, String path, String filename, String content) throws InterruptedException { + private void isPathPresent(String routerIp, String path, String filename, String content) throws InterruptedException { String errMsg = "Failed to scp file: %s to system VM"; for (int retries = 15; retries > 0; retries--) { try { - _vrDeployer.createFileInVR(routerIp, path, filename, content); + ExecutionResult result = _vrDeployer.createFileInVR(routerIp, path, filename, content); + if (result.isSuccess()) { + break; + } } catch (Exception e) { errMsg += ", retrying"; s_logger.error(String.format(errMsg, filename), e); @@ -190,7 +193,7 @@ private Answer execute(final SetupCertificateCommand cmd) { String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); if (!org.apache.commons.lang3.StringUtils.isEmpty(routerName) && (routerName.startsWith("s-") || routerName.startsWith("v-"))) { try { - scpFileToIdentifyPatching(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.CERT_FILENAME, cmd.getCertificate()); + isPathPresent(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.CERT_FILENAME, cmd.getCertificate()); } catch (InterruptedException e) { throw new CloudRuntimeException(String.format("Failed to scp certificate file to %s due to %s", routerName, e.getLocalizedMessage())); } diff --git a/core/src/main/java/com/cloud/resource/ServerResource.java b/core/src/main/java/com/cloud/resource/ServerResource.java index 0afb040b249f..1602a78d9a47 100644 --- a/core/src/main/java/com/cloud/resource/ServerResource.java +++ b/core/src/main/java/com/cloud/resource/ServerResource.java @@ -28,8 +28,6 @@ import com.cloud.utils.component.Manager; import org.apache.cloudstack.utils.security.KeyStoreUtils; -import java.io.File; - /** * ServerResource is a generic container to execute commands sent */ @@ -39,7 +37,7 @@ public interface ServerResource extends Manager { String[] certificateFiles = new String[] {KeyStoreUtils.CERT_FILENAME, KeyStoreUtils.CACERT_FILENAME, KeyStoreUtils.PKEY_FILENAME}; String SSHKEYSPATH = "/root/.ssh"; - String SSHPRVKEYPATH = SSHKEYSPATH + File.separator + "id_rsa.cloud"; + String SSHPRVKEYPATH = SSHKEYSPATH +"/id_rsa.cloud"; /** * @return Host.Type type of the computing server we have. diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index b2b7050bb8fc..0b1d24ecb5b6 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -332,7 +332,6 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv protected String _hostDistro; protected String _networkDirectSourceMode; protected String _networkDirectDevice; - protected String _sysvmISOPath; protected String _privNwName; protected String _privBridgeName; protected String _linkLocalBridgeName; @@ -2887,7 +2886,6 @@ public int compare(final DiskTO arg0, final DiskTO arg1) { if (vmSpec.getType() != VirtualMachine.Type.User) { final DiskDef iso = new DiskDef(); - iso.defISODisk(_sysvmISOPath); if (_guestCpuArch != null && _guestCpuArch.equals("aarch64")) { iso.setBusType(DiskDef.DiskBus.SCSI); } diff --git a/scripts/util/keystore-cert-import b/scripts/util/keystore-cert-import index 64ae92bcfdc3..9e4e7f246b31 100755 --- a/scripts/util/keystore-cert-import +++ b/scripts/util/keystore-cert-import @@ -43,13 +43,6 @@ if [ ! -f "$LIBVIRTD_FILE" ]; then echo "keystore.passphrase=$KS_PASS" >> $PROPS_FILE fi fi - -# if [ -f "$KS_FILE" ]; then -# keytool -delete -noprompt -alias "$ALIAS" -keystore "$KS_FILE" -storepass "$KS_PASS" > /dev/null 2>&1 || true -# fi -# -# CN=$(hostname --fqdn) -# keytool -genkey -storepass "$KS_PASS" -keypass "$KS_PASS" -alias "$ALIAS" -keyalg RSA -validity "$KS_VALIDITY" -dname cn="$CN",ou="cloudstack",o="cloudstack",c="cloudstack" -keystore "$KS_FILE" > /dev/null 2>&1 fi # Find keystore password diff --git a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 15ab2cc44907..a3cfe8993650 100644 --- a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -1285,7 +1285,6 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl buf.append(" dns2=").append(dc.getDns2()); } buf.append(" keystore_password=").append(VirtualMachineGuru.getEncodedString(PasswordGenerator.generateRandomPassword(16))); -// VirtualMachineGuru.appendCertificateDetails(buf, certificate); String bootArgs = buf.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug("Boot Args for " + profile + ": " + bootArgs); diff --git a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java index 6c9ce8570551..561c480237f7 100644 --- a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java +++ b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java @@ -31,6 +31,7 @@ import java.util.Properties; import java.util.concurrent.Executor; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.xml.DOMConfigurator; import org.eclipse.jetty.websocket.api.Session; @@ -110,9 +111,9 @@ private static void configProxy(Properties conf) { s_logger.info("Configure console proxy..."); for (Object key : conf.keySet()) { s_logger.info("Property " + (String)key + ": " + conf.getProperty((String)key)); -// if (!ArrayUtils.contains(skipProperties, key)) { -// s_logger.info("Property " + (String)key + ": " + conf.getProperty((String)key)); -// } + if (!ArrayUtils.contains(skipProperties, key)) { + s_logger.info("Property " + (String)key + ": " + conf.getProperty((String)key)); + } } String s = conf.getProperty("consoleproxy.httpListenPort"); @@ -251,10 +252,9 @@ public static void startWithContext(Properties conf, Object context, byte[] ksBi if (conf != null) { for (Object key : conf.keySet()) { -// if (!ArrayUtils.contains(skipProperties, key)) { - s_logger.info("Context property " + (String) key + ": " + conf.getProperty((String) key)); -// s_logger.info("Context property " + (String) key + ": " + conf.getProperty((String) key)); -// } + if (!ArrayUtils.contains(skipProperties, key)) { + s_logger.info("Context property " + (String) key + ": " + conf.getProperty((String) key)); + } } } diff --git a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java index f2db365d8dda..7132c5d5717c 100644 --- a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java +++ b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java @@ -1166,7 +1166,6 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl String nfsVersion = imageStoreDetailsUtil != null ? imageStoreDetailsUtil.getNfsVersion(secStore.getId()) : null; buf.append(" nfsVersion=").append(nfsVersion); buf.append(" keystore_password=").append(VirtualMachineGuru.getEncodedString(PasswordGenerator.generateRandomPassword(16))); - //VirtualMachineGuru.appendCertificateDetails(buf, certificate); String bootArgs = buf.toString(); if (s_logger.isDebugEnabled()) { s_logger.debug(String.format("Boot args for machine profile [%s]: [%s].", profile.toString(), bootArgs)); diff --git a/systemvm/debian/etc/systemd/system/cloud-postinit.service b/systemvm/debian/etc/systemd/system/cloud-postinit.service index f5b23e230877..31a1f3b8f597 100644 --- a/systemvm/debian/etc/systemd/system/cloud-postinit.service +++ b/systemvm/debian/etc/systemd/system/cloud-postinit.service @@ -1,7 +1,6 @@ [Unit] Description=CloudStack post-patching init script After=cloud-early-config.service network.target local-fs.target -#Before=ssh.service [Install] WantedBy=multi-user.target From fb1678c4b4476b83c0d0b85b7914c3848928efdc Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Thu, 10 Mar 2022 19:46:53 +0530 Subject: [PATCH 53/68] address comments --- .../resource/virtualnetwork/VRScripts.java | 1 + .../VirtualRoutingResource.java | 42 +++++++++---------- .../LibvirtPatchSystemVmCommandWrapper.java | 4 +- .../wrapper/LibvirtStartCommandWrapper.java | 8 +++- .../LibvirtComputingResourceTest.java | 2 + .../vmware/resource/VmwareResource.java | 12 ++++-- .../CitrixPatchSystemVmCommandWrapper.java | 2 +- .../xenbase/CitrixStartCommandWrapper.java | 10 ++++- scripts/vm/hypervisor/xenserver/vmops | 2 +- systemvm/debian/opt/cloud/bin/patched.sh | 19 +++++++++ .../debian/opt/cloud/bin/setup/bootstrap.sh | 2 +- .../opt/cloud/bin/setup/cloud-early-config | 7 ++-- systemvm/patch-sysvms.sh | 2 +- 13 files changed, 72 insertions(+), 41 deletions(-) create mode 100644 systemvm/debian/opt/cloud/bin/patched.sh diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VRScripts.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VRScripts.java index 834a11c8d6eb..a76d555b002b 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VRScripts.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VRScripts.java @@ -41,6 +41,7 @@ public class VRScripts { public static final String IP_ALIAS_CONFIG = "ip_aliases.json"; public static final String LOAD_BALANCER_CONFIG = "load_balancer.json"; + public static final String SYSTEM_VM_PATCHED = "patched.sh"; public final static String CONFIG_CACHE_LOCATION = "/var/cache/cloud/"; public final static Duration VR_SCRIPT_EXEC_TIMEOUT = Duration.standardMinutes(10); public final static Duration CONNECTION_TIMEOUT = Duration.standardMinutes(1); diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java index 3fe8470c0b69..8a265a78123b 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java @@ -174,30 +174,7 @@ private Answer execute(final SetupKeyStoreCommand cmd) { return new SetupKeystoreAnswer(result.getDetails()); } - private void isPathPresent(String routerIp, String path, String filename, String content) throws InterruptedException { - String errMsg = "Failed to scp file: %s to system VM"; - for (int retries = 15; retries > 0; retries--) { - try { - ExecutionResult result = _vrDeployer.createFileInVR(routerIp, path, filename, content); - if (result.isSuccess()) { - break; - } - } catch (Exception e) { - errMsg += ", retrying"; - s_logger.error(String.format(errMsg, filename), e); - Thread.sleep(2000); - } - } - } private Answer execute(final SetupCertificateCommand cmd) { - String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); - if (!org.apache.commons.lang3.StringUtils.isEmpty(routerName) && (routerName.startsWith("s-") || routerName.startsWith("v-"))) { - try { - isPathPresent(cmd.getRouterAccessIp(), "/usr/local/cloud/systemvm/conf/", KeyStoreUtils.CERT_FILENAME, cmd.getCertificate()); - } catch (InterruptedException e) { - throw new CloudRuntimeException(String.format("Failed to scp certificate file to %s due to %s", routerName, e.getLocalizedMessage())); - } - } final String args = String.format("/usr/local/cloud/systemvm/conf/agent.properties %s " + "/usr/local/cloud/systemvm/conf/%s %s " + "/usr/local/cloud/systemvm/conf/%s \"%s\" " + @@ -607,4 +584,23 @@ private Answer execute(AggregationControlCommand cmd) { } return new Answer(cmd, false, "Fail to recognize aggregation action " + action.toString()); } + + public boolean isSystemVMSetup(String vmName, String controlIp) throws InterruptedException { + if (vmName.startsWith("s-") || vmName.startsWith("v-")) { + ScriptConfigItem scriptConfigItem = new ScriptConfigItem(VRScripts.SYSTEM_VM_PATCHED, "/opt/cloud/bin/keystore*"); + ExecutionResult result = new ExecutionResult(false, ""); + int retries = 0; + while (!result.isSuccess() && retries < 600) { + result = applyConfigToVR(controlIp, scriptConfigItem, VRScripts.VR_SCRIPT_EXEC_TIMEOUT); + if (result.isSuccess()) { + return true; + } + + retries++; + Thread.sleep(1000); + } + return false; + } + return true; + } } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java index 8d4700bf5694..7c6bb1fcb48b 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java @@ -70,9 +70,9 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR Pair patchResult = null; try { - FileUtil.scpPatchFiles(controlIp, "/home/cloud", sshPort, pemFile, serverResource.systemVmPatchFiles, LibvirtComputingResource.BASEPATH); + FileUtil.scpPatchFiles(controlIp, "/tmp/", sshPort, pemFile, serverResource.systemVmPatchFiles, LibvirtComputingResource.BASEPATH); patchResult = SshHelper.sshExecute(controlIp, sshPort, "root", - pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 600000); + pemFile, null, "/tmp/patch-sysvms.sh", 10000, 10000, 600000); } catch (Exception e) { return new PatchSystemVmAnswer(cmd, e.getMessage()); } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java index c89a28386105..bdb86f061e96 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java @@ -120,8 +120,12 @@ public Answer execute(final StartCommand command, final LibvirtComputingResource try { File pemFile = new File(LibvirtComputingResource.SSHPRVKEYPATH); - FileUtil.scpPatchFiles(controlIp, "/home/cloud", Integer.parseInt(LibvirtComputingResource.DEFAULTDOMRSSHPORT), pemFile, LibvirtComputingResource.systemVmPatchFiles, LibvirtComputingResource.BASEPATH); - Thread.sleep(10000); + FileUtil.scpPatchFiles(controlIp, "/tmp/", Integer.parseInt(LibvirtComputingResource.DEFAULTDOMRSSHPORT), pemFile, LibvirtComputingResource.systemVmPatchFiles, LibvirtComputingResource.BASEPATH); + if (!virtRouterResource.isSystemVMSetup(vmName, controlIp)) { + String errMsg = "Failed to patch systemVM"; + s_logger.error(errMsg); + return new StartAnswer(command, errMsg); + } } catch (Exception e) { String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; s_logger.error(errMsg, e); diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java index c4741bb2f30e..3b9f36e34074 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java @@ -5333,6 +5333,7 @@ public void testStartCommand() throws Exception { when(nic.getType()).thenReturn(TrafficType.Control); when(libvirtComputingResource.getVirtRouterResource()).thenReturn(virtRouterResource); when(virtRouterResource.connect(controlIp, 1, 5000)).thenReturn(true); + when(virtRouterResource.isSystemVMSetup(vmName, controlIp)).thenReturn(true); } catch (final InternalErrorException e) { fail(e.getMessage()); } catch (final LibvirtException e) { @@ -5413,6 +5414,7 @@ public void testStartCommandIsolationEc2() throws Exception { when(nic.getType()).thenReturn(TrafficType.Control); when(libvirtComputingResource.getVirtRouterResource()).thenReturn(virtRouterResource); when(virtRouterResource.connect(controlIp, 1, 5000)).thenReturn(true); + when(virtRouterResource.isSystemVMSetup(vmName, controlIp)).thenReturn(true); } catch (final InternalErrorException e) { fail(e.getMessage()); } catch (final LibvirtException e) { diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index d36c808f3961..21f6a4712ca9 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -662,7 +662,7 @@ private Answer execute(PatchSystemVmCommand cmd) { ExecutionResult result = getSystemVmVersionAndChecksum(controlIp); try { - FileUtil.scpPatchFiles(controlIp, "/home/cloud", DefaultDomRSshPort, pemFile, systemVmPatchFiles, BASEPATH); + FileUtil.scpPatchFiles(controlIp, "/tmp/", DefaultDomRSshPort, pemFile, systemVmPatchFiles, BASEPATH); } catch (CloudRuntimeException e) { return new PatchSystemVmAnswer(cmd, e.getMessage()); } @@ -687,7 +687,7 @@ private Answer execute(PatchSystemVmCommand cmd) { Pair patchResult = null; try { patchResult = SshHelper.sshExecute(controlIp, DefaultDomRSshPort, "root", - pemFile, null, "/home/cloud/patch-sysvms.sh", 10000, 10000, 600000); + pemFile, null, "/tmp/patch-sysvms.sh", 10000, 10000, 600000); } catch (Exception e) { return new PatchSystemVmAnswer(cmd, e.getMessage()); } @@ -2578,8 +2578,12 @@ protected StartAnswer execute(StartCommand cmd) { try { String homeDir = System.getProperty("user.home"); File pemFile = new File(homeDir + "/.ssh/id_rsa"); - FileUtil.scpPatchFiles(controlIp, "/home/cloud", DefaultDomRSshPort, pemFile, systemVmPatchFiles, BASEPATH); - Thread.sleep(10000); + FileUtil.scpPatchFiles(controlIp, "/tmp/", DefaultDomRSshPort, pemFile, systemVmPatchFiles, BASEPATH); + if (!_vrResource.isSystemVMSetup(vmInternalCSName, controlIp)) { + String errMsg = "Failed to patch systemVM"; + s_logger.error(errMsg); + return new StartAnswer(cmd, errMsg); + } } catch (Exception e) { String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; s_logger.error(errMsg, e); diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java index e806e7e27d55..3495f7f03e57 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java @@ -68,7 +68,7 @@ public Answer execute(PatchSystemVmCommand command, CitrixResourceBase serverRes } String patchResult = null; try { - serverResource.copyPatchFilesToVR(controlIp, "/home/cloud"); + serverResource.copyPatchFilesToVR(controlIp, "/tmp/"); patchResult = serverResource.callHostPlugin(conn, "vmops", "runPatchScriptInDomr", "domrip", controlIp); } catch (Exception e) { return new PatchSystemVmAnswer(command, e.getMessage()); diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java index 58eea712d3f0..7b1d6aeac6fd 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java @@ -25,6 +25,7 @@ import java.util.Map; import java.util.Set; +import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; @@ -195,8 +196,13 @@ public Answer execute(final StartCommand command, final CitrixResourceBase citri } try { - citrixResourceBase.copyPatchFilesToVR(controlIp, "/home/cloud"); - Thread.sleep(10000); + citrixResourceBase.copyPatchFilesToVR(controlIp, "/tmp/"); + VirtualRoutingResource vrResource = citrixResourceBase.getVirtualRoutingResource(); + if (!vrResource.isSystemVMSetup(vmName, controlIp)) { + String errMsg = "Failed to patch systemVM"; + s_logger.error(errMsg); + return new StartAnswer(command, errMsg); + } } catch (Exception e) { String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; s_logger.error(errMsg, e); diff --git a/scripts/vm/hypervisor/xenserver/vmops b/scripts/vm/hypervisor/xenserver/vmops index cea47cce2975..de5feb06d21d 100755 --- a/scripts/vm/hypervisor/xenserver/vmops +++ b/scripts/vm/hypervisor/xenserver/vmops @@ -254,7 +254,7 @@ def runPatchScriptInDomr(session, args): txt="" try: target = "root@" + domrip - txt = util.pread2(['ssh','-p','3922','-i','/root/.ssh/id_rsa.cloud', target, "/bin/bash","/home/cloud/patch-sysvms.sh"]) + txt = util.pread2(['ssh','-p','3922','-i','/root/.ssh/id_rsa.cloud', target, "/bin/bash","/tmp/patch-sysvms.sh"]) txt = 'succ#' + txt except: logging.debug("failed to run patch script in systemVM with IP: " + domrip) diff --git a/systemvm/debian/opt/cloud/bin/patched.sh b/systemvm/debian/opt/cloud/bin/patched.sh new file mode 100644 index 000000000000..bfe0f64495aa --- /dev/null +++ b/systemvm/debian/opt/cloud/bin/patched.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +ls -lrt $1 \ No newline at end of file diff --git a/systemvm/debian/opt/cloud/bin/setup/bootstrap.sh b/systemvm/debian/opt/cloud/bin/setup/bootstrap.sh index 3f64be778232..4720237543fb 100755 --- a/systemvm/debian/opt/cloud/bin/setup/bootstrap.sh +++ b/systemvm/debian/opt/cloud/bin/setup/bootstrap.sh @@ -55,7 +55,7 @@ patch_systemvm() { } patch() { - local PATCH_MOUNT=/home/cloud + local PATCH_MOUNT=/tmp/ local logfile="/var/log/patchsystemvm.log" if [ "$TYPE" == "consoleproxy" ] || [ "$TYPE" == "secstorage" ] && [ -f ${PATCH_MOUNT}/agent.zip ] && [ -f /var/cache/cloud/patch.required ] diff --git a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config index 1227c68850b9..d76079b69e49 100755 --- a/systemvm/debian/opt/cloud/bin/setup/cloud-early-config +++ b/systemvm/debian/opt/cloud/bin/setup/cloud-early-config @@ -41,7 +41,7 @@ validate_checksums() { } patch() { - local PATCH_MOUNT=/home/cloud + local PATCH_MOUNT=/tmp local PATCH_SCRIPTS=cloud-scripts.tgz local oldpatchfile=/usr/share/cloud/$PATCH_SCRIPTS local patchfile=$PATCH_MOUNT/$PATCH_SCRIPTS @@ -71,7 +71,6 @@ patch() { if [ "$oldmd5" != "$newmd5" ] && [ -f ${patchfile} ] && [ "$newmd5" != "" ] then tar xzf $patchfile -C / - ls -lrt /opt/cloud/bin/keystore* echo ${newmd5} > ${md5file} log_it "Patched scripts using $patchfile" touch /var/cache/cloud/patch.required @@ -98,8 +97,8 @@ patch() { } cleanup() { - rm -rf /home/cloud/agent.zip - mv /home/cloud/cloud-scripts.tgz /usr/share/cloud/cloud-scripts.tgz + rm -rf /tmp/agent.zip + mv /tmp/cloud-scripts.tgz /usr/share/cloud/cloud-scripts.tgz } start() { diff --git a/systemvm/patch-sysvms.sh b/systemvm/patch-sysvms.sh index 4a6873147b8f..62e0dd6f1a87 100644 --- a/systemvm/patch-sysvms.sh +++ b/systemvm/patch-sysvms.sh @@ -19,7 +19,7 @@ PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" backupfolder=/tmp/bkpup_live_patch logfile="/var/log/livepatchsystemvm.log" -newpath="/home/cloud/" +newpath="/tmp/" CMDLINE=/var/cache/cloud/cmdline md5file=/var/cache/cloud/cloud-scripts-signature svcfile=/var/cache/cloud/enabled_svcs From cb47ea46e40961bf215389fb78c120fe7e814e68 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Wed, 16 Mar 2022 11:08:16 +0530 Subject: [PATCH 54/68] update containerd config - as version has upgraded to 1.5 from 1.4.12 in 4.17.0 --- .../src/main/resources/conf/k8s-control-node-add.yml | 2 +- .../src/main/resources/conf/k8s-control-node.yml | 2 +- .../kubernetes-service/src/main/resources/conf/k8s-node.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml index 89138a58d08b..335ae9194e6d 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml @@ -262,7 +262,7 @@ write_files: runcmd: - chown -R cloud:cloud /home/cloud/.ssh - containerd config default > /etc/containerd/config.toml - - sed -i '/\[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options\]/a '"\\ SystemdCgroup=true"'' /etc/containerd/config.toml + - sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml - systemctl daemon-reload - systemctl restart containerd - until [ -f /etc/systemd/system/deploy-kube-system.service ]; do sleep 5; done diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml index f423d6410e05..76adc5a7d296 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node.yml @@ -319,7 +319,7 @@ write_files: runcmd: - chown -R cloud:cloud /home/cloud/.ssh - containerd config default > /etc/containerd/config.toml - - sed -i '/\[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options\]/a '"\\ SystemdCgroup=true"'' /etc/containerd/config.toml + - sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml - systemctl daemon-reload - systemctl restart containerd - until [ -f /etc/systemd/system/deploy-kube-system.service ]; do sleep 5; done diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml index d253f3e27803..86966245c83e 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-node.yml @@ -262,7 +262,7 @@ write_files: runcmd: - chown -R cloud:cloud /home/cloud/.ssh - containerd config default > /etc/containerd/config.toml - - sed -i '/\[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options\]/a '"\\ SystemdCgroup=true"'' /etc/containerd/config.toml + - sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml - systemctl daemon-reload - systemctl restart containerd - until [ -f /etc/systemd/system/deploy-kube-system.service ]; do sleep 5; done From 0589ef86c8e36531f1ef28c8960174c6483ed7ef Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Thu, 17 Mar 2022 10:26:30 +0530 Subject: [PATCH 55/68] address comments - simplify --- .../command/admin/systemvm/PatchSystemVMCmd.java | 2 +- .../LibvirtPatchSystemVmCommandWrapper.java | 12 +++++------- .../vmware/resource/VmwareResource.java | 16 +++++++--------- .../CitrixPatchSystemVmCommandWrapper.java | 11 +++++------ 4 files changed, 18 insertions(+), 23 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java index ea6240549109..12699ba9b6c2 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java @@ -62,7 +62,7 @@ public Long getId() { } public boolean isForced() { - return force != null ? force : false; + return force != null && force; } ///////////////////////////////////////////////////// diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java index 7c6bb1fcb48b..726ed1b5ff03 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java @@ -60,12 +60,10 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR String scriptChecksum = lines[1].trim(); String checksum = serverResource.calculateCurrentChecksum(sysVMName, "vms/cloud-scripts.tgz").trim(); - if (!StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum)) { - if (!cmd.isForced()) { - String msg = String.format("No change in the scripts checksum, not patching systemVM %s", sysVMName); - s_logger.info(msg); - return new PatchSystemVmAnswer(cmd, msg, lines[0], lines[1]); - } + if (!StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum) && !cmd.isForced()) { + String msg = String.format("No change in the scripts checksum, not patching systemVM %s", sysVMName); + s_logger.info(msg); + return new PatchSystemVmAnswer(cmd, msg, lines[0], lines[1]); } Pair patchResult = null; @@ -79,7 +77,7 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR if (patchResult.first()) { String scriptVersion = lines[1]; - if (patchResult.second() != null) { + if (StringUtils.isNotEmpty(patchResult.second())) { String res = patchResult.second().replace("\n", " "); String[] output = res.split(":"); if (output.length != 2) { diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 21f6a4712ca9..f9ce79e91fe8 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -659,9 +659,9 @@ private Answer execute(PatchSystemVmCommand cmd) { String sysVMName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); String homeDir = System.getProperty("user.home"); File pemFile = new File(homeDir + "/.ssh/id_rsa"); - - ExecutionResult result = getSystemVmVersionAndChecksum(controlIp); + ExecutionResult result; try { + result = getSystemVmVersionAndChecksum(controlIp); FileUtil.scpPatchFiles(controlIp, "/tmp/", DefaultDomRSshPort, pemFile, systemVmPatchFiles, BASEPATH); } catch (CloudRuntimeException e) { return new PatchSystemVmAnswer(cmd, e.getMessage()); @@ -676,12 +676,10 @@ private Answer execute(PatchSystemVmCommand cmd) { String scriptChecksum = lines[1].trim(); String checksum = calculateCurrentChecksum(sysVMName, "vms/cloud-scripts.tgz").trim(); - if (!org.apache.commons.lang3.StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum)) { - if (!cmd.isForced()) { - String msg = String.format("No change in the scripts checksum, not patching systemVM %s", sysVMName); - s_logger.info(msg); - return new PatchSystemVmAnswer(cmd, msg, lines[0], lines[1]); - } + if (!org.apache.commons.lang3.StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum) && !cmd.isForced()) { + String msg = String.format("No change in the scripts checksum, not patching systemVM %s", sysVMName); + s_logger.info(msg); + return new PatchSystemVmAnswer(cmd, msg, lines[0], lines[1]); } Pair patchResult = null; @@ -693,7 +691,7 @@ private Answer execute(PatchSystemVmCommand cmd) { } String scriptVersion = lines[1]; - if (patchResult.second() != null) { + if (StringUtils.isNotEmpty(patchResult.second())) { String res = patchResult.second().replace("\n", " "); String[] output = res.split(":"); if (output.length != 2) { diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java index 3495f7f03e57..b67438d9dbbf 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java @@ -59,13 +59,12 @@ public Answer execute(PatchSystemVmCommand command, CitrixResourceBase serverRes String scriptChecksum = lines[1].trim(); String checksum = serverResource.calculateCurrentChecksum(sysVMName, "vms/cloud-scripts.tgz").trim(); - if (!StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum)) { - if (!command.isForced()) { - String msg = String.format("No change in the scripts checksum, not patching systemVM %s", sysVMName); - s_logger.info(msg); - return new PatchSystemVmAnswer(command, msg, lines[0], lines[1]); - } + if (!StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum) && !command.isForced()) { + String msg = String.format("No change in the scripts checksum, not patching systemVM %s", sysVMName); + s_logger.info(msg); + return new PatchSystemVmAnswer(command, msg, lines[0], lines[1]); } + String patchResult = null; try { serverResource.copyPatchFilesToVR(controlIp, "/tmp/"); From e40625e76d9e74e36b13545ddb90407ae4bd2379 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Tue, 22 Mar 2022 11:32:07 +0530 Subject: [PATCH 56/68] fix vue3 related icon changes --- ui/src/config/section/infra/systemVms.js | 2 +- ui/src/core/lazy_lib/icons_use.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/src/config/section/infra/systemVms.js b/ui/src/config/section/infra/systemVms.js index 5875c659ec93..9808f72fa51d 100644 --- a/ui/src/config/section/infra/systemVms.js +++ b/ui/src/config/section/infra/systemVms.js @@ -139,7 +139,7 @@ export default { }, { api: 'patchSystemVm', - icon: 'diff', + icon: 'diff-outlined', label: 'label.action.patch.systemvm', message: 'message.action.patch.systemvm', dataView: true, diff --git a/ui/src/core/lazy_lib/icons_use.js b/ui/src/core/lazy_lib/icons_use.js index a01b2875856d..d3a1ead374af 100644 --- a/ui/src/core/lazy_lib/icons_use.js +++ b/ui/src/core/lazy_lib/icons_use.js @@ -65,6 +65,7 @@ import { DoubleRightOutlined, DownOutlined, DownloadOutlined, + DiffOutlined, DragOutlined, EditOutlined, EnvironmentOutlined, @@ -204,6 +205,7 @@ export default { app.component('DoubleRightOutlined', DoubleRightOutlined) app.component('DownOutlined', DownOutlined) app.component('DownloadOutlined', DownloadOutlined) + app.component('DiffOutlined', DiffOutlined) app.component('DragOutlined', DragOutlined) app.component('EditOutlined', EditOutlined) app.component('EnvironmentOutlined', EnvironmentOutlined) From 3d1ec29c6fd9e3d4093d677fca8a8d1b09c55b60 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Fri, 25 Mar 2022 12:29:28 +0530 Subject: [PATCH 57/68] allow network commands when router template version is lower but is patched --- .../cloud/network/router/VirtualRouter.java | 2 ++ .../cloud/resource/ServerResourceBase.java | 12 ------- .../LibvirtPatchSystemVmCommandWrapper.java | 3 +- .../vmware/resource/VmwareResource.java | 3 +- .../CitrixPatchSystemVmCommandWrapper.java | 3 +- .../network/router/NetworkHelperImpl.java | 10 +++++- .../cloud/utils/validation/ChecksumUtil.java | 34 +++++++++++++++++++ 7 files changed, 51 insertions(+), 16 deletions(-) create mode 100644 utils/src/main/java/com/cloud/utils/validation/ChecksumUtil.java diff --git a/api/src/main/java/com/cloud/network/router/VirtualRouter.java b/api/src/main/java/com/cloud/network/router/VirtualRouter.java index 8bec51990470..c4ae4e964cf5 100644 --- a/api/src/main/java/com/cloud/network/router/VirtualRouter.java +++ b/api/src/main/java/com/cloud/network/router/VirtualRouter.java @@ -52,4 +52,6 @@ public enum RedundantState { Long getVpcId(); String getTemplateVersion(); + + String getScriptsVersion(); } diff --git a/core/src/main/java/com/cloud/resource/ServerResourceBase.java b/core/src/main/java/com/cloud/resource/ServerResourceBase.java index 99c9e2ee1058..f68bcf409ef3 100644 --- a/core/src/main/java/com/cloud/resource/ServerResourceBase.java +++ b/core/src/main/java/com/cloud/resource/ServerResourceBase.java @@ -19,7 +19,6 @@ package com.cloud.resource; -import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; import java.net.NetworkInterface; @@ -33,8 +32,6 @@ import javax.naming.ConfigurationException; -import com.cloud.utils.exception.CloudRuntimeException; -import org.apache.cloudstack.utils.security.DigestHelper; import org.apache.log4j.Logger; import com.cloud.agent.IAgentControl; @@ -309,13 +306,4 @@ public boolean start() { public boolean stop() { return true; } - - public String calculateCurrentChecksum(String name, String path) { - String cloudScriptsPath = Script.findScript("", path); - if (cloudScriptsPath == null) { - throw new CloudRuntimeException(String.format("Unable to find cloudScripts path, cannot update SystemVM %s", name)); - } - String md5sum = DigestHelper.calculateChecksum(new File(cloudScriptsPath)); - return md5sum; - } } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java index 726ed1b5ff03..691d34fd7096 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPatchSystemVmCommandWrapper.java @@ -29,6 +29,7 @@ import com.cloud.utils.Pair; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.ssh.SshHelper; +import com.cloud.utils.validation.ChecksumUtil; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; @@ -58,7 +59,7 @@ public Answer execute(PatchSystemVmCommand cmd, LibvirtComputingResource serverR } String scriptChecksum = lines[1].trim(); - String checksum = serverResource.calculateCurrentChecksum(sysVMName, "vms/cloud-scripts.tgz").trim(); + String checksum = ChecksumUtil.calculateCurrentChecksum(sysVMName, "vms/cloud-scripts.tgz").trim(); if (!StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum) && !cmd.isForced()) { String msg = String.format("No change in the scripts checksum, not patching systemVM %s", sysVMName); diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index f9ce79e91fe8..247b549a81dd 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -51,6 +51,7 @@ import com.cloud.agent.api.PatchSystemVmCommand; import com.cloud.resource.ServerResourceBase; import com.cloud.utils.FileUtil; +import com.cloud.utils.validation.ChecksumUtil; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.storage.command.CopyCommand; import org.apache.cloudstack.storage.command.StorageSubSystemCommand; @@ -674,7 +675,7 @@ private Answer execute(PatchSystemVmCommand cmd) { } String scriptChecksum = lines[1].trim(); - String checksum = calculateCurrentChecksum(sysVMName, "vms/cloud-scripts.tgz").trim(); + String checksum = ChecksumUtil.calculateCurrentChecksum(sysVMName, "vms/cloud-scripts.tgz").trim(); if (!org.apache.commons.lang3.StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum) && !cmd.isForced()) { String msg = String.format("No change in the scripts checksum, not patching systemVM %s", sysVMName); diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java index b67438d9dbbf..718daec72926 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixPatchSystemVmCommandWrapper.java @@ -26,6 +26,7 @@ import com.cloud.resource.ResourceWrapper; import com.cloud.utils.ExecutionResult; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.validation.ChecksumUtil; import com.xensource.xenapi.Connection; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; @@ -58,7 +59,7 @@ public Answer execute(PatchSystemVmCommand command, CitrixResourceBase serverRes } String scriptChecksum = lines[1].trim(); - String checksum = serverResource.calculateCurrentChecksum(sysVMName, "vms/cloud-scripts.tgz").trim(); + String checksum = ChecksumUtil.calculateCurrentChecksum(sysVMName, "vms/cloud-scripts.tgz").trim(); if (!StringUtils.isEmpty(checksum) && checksum.equals(scriptChecksum) && !command.isForced()) { String msg = String.format("No change in the scripts checksum, not patching systemVM %s", sysVMName); s_logger.info(msg); diff --git a/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java b/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java index cc947bd05031..d7c9ee225bc7 100644 --- a/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java +++ b/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java @@ -27,6 +27,7 @@ import javax.annotation.PostConstruct; import javax.inject.Inject; +import com.cloud.utils.validation.ChecksumUtil; import org.apache.cloudstack.api.ApiConstants; import org.apache.log4j.Logger; import org.cloud.network.router.deployment.RouterDeploymentDefinition; @@ -278,7 +279,14 @@ public boolean checkRouterVersion(final VirtualRouter router) { } final long dcid = router.getDataCenterId(); String routerVersion = CloudStackVersion.trimRouterVersion(router.getTemplateVersion()); - return CloudStackVersion.compare(routerVersion, NetworkOrchestrationService.MinVRVersion.valueIn(dcid)) >= 0; + String currentCheckSum = ChecksumUtil.calculateCurrentChecksum(router.getName(), "vms/cloud-scripts.tgz"); + String routerChecksum = router.getScriptsVersion() == null ? "" : router.getScriptsVersion(); + boolean routerVersionMatch = CloudStackVersion.compare(routerVersion, NetworkOrchestrationService.MinVRVersion.valueIn(dcid)) >= 0; + if (routerVersionMatch) { + return true; + } + boolean routerCheckSumMatch = currentCheckSum.equals(routerChecksum); + return routerCheckSumMatch; } protected DomainRouterVO start(DomainRouterVO router, final User user, final Account caller, final Map params, final DeploymentPlan planToDeploy) diff --git a/utils/src/main/java/com/cloud/utils/validation/ChecksumUtil.java b/utils/src/main/java/com/cloud/utils/validation/ChecksumUtil.java new file mode 100644 index 000000000000..b1b675bca0a0 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/validation/ChecksumUtil.java @@ -0,0 +1,34 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.utils.validation; + +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; +import org.apache.cloudstack.utils.security.DigestHelper; + +import java.io.File; + +public class ChecksumUtil { + public static String calculateCurrentChecksum(String name, String path) { + String cloudScriptsPath = Script.findScript("", path); + if (cloudScriptsPath == null) { + throw new CloudRuntimeException(String.format("Unable to find cloudScripts path, cannot update SystemVM %s", name)); + } + String md5sum = DigestHelper.calculateChecksum(new File(cloudScriptsPath)); + return md5sum; + } +} From 971eac5c17f5750dc12b6e1d07e818150cb3482a Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Fri, 25 Mar 2022 13:03:36 +0530 Subject: [PATCH 58/68] add internal LB to the list of routers to be patched on network restart with live patch --- .../engine/orchestration/NetworkOrchestrator.java | 2 +- .../src/main/java/com/cloud/vm/dao/DomainRouterDao.java | 2 +- .../src/main/java/com/cloud/vm/dao/DomainRouterDaoImpl.java | 6 +++--- .../main/java/com/cloud/server/ManagementServerImpl.java | 5 ++++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index ce80f4836bab..f5f2f2d187f9 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -3296,7 +3296,7 @@ public boolean restartNetwork(final Long networkId, final Account callerAccount, setRestartRequired(network, restartRequired); return status; } else if (livePatch) { - List domainRouters = routerDao.listByNetworkAndRole(network.getId(), VirtualRouter.Role.VIRTUAL_ROUTER); + List domainRouters = routerDao.listByNetworkAndRole(network.getId(), VirtualRouter.Role.VIRTUAL_ROUTER, VirtualRouter.Role.INTERNAL_LB_VM); for (DomainRouterVO router: domainRouters) { try { VMInstanceVO instanceVO = _vmDao.findById(router.getId()); diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/DomainRouterDao.java b/engine/schema/src/main/java/com/cloud/vm/dao/DomainRouterDao.java index c4fd2f6c974d..8e965b210beb 100644 --- a/engine/schema/src/main/java/com/cloud/vm/dao/DomainRouterDao.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/DomainRouterDao.java @@ -121,7 +121,7 @@ public interface DomainRouterDao extends GenericDao { List listByNetworkAndPodAndRole(long networkId, long podId, Role role); - List listByNetworkAndRole(long networkId, Role role); + List listByNetworkAndRole(long networkId, Role... roles); List listByElementId(long elementId); diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/DomainRouterDaoImpl.java b/engine/schema/src/main/java/com/cloud/vm/dao/DomainRouterDaoImpl.java index dc71f898970b..6150ab9cc397 100644 --- a/engine/schema/src/main/java/com/cloud/vm/dao/DomainRouterDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/DomainRouterDaoImpl.java @@ -78,7 +78,7 @@ protected void init() { AllFieldsSearch = createSearchBuilder(); AllFieldsSearch.and("dc", AllFieldsSearch.entity().getDataCenterId(), Op.EQ); AllFieldsSearch.and("account", AllFieldsSearch.entity().getAccountId(), Op.EQ); - AllFieldsSearch.and("role", AllFieldsSearch.entity().getRole(), Op.EQ); + AllFieldsSearch.and("role", AllFieldsSearch.entity().getRole(), Op.IN); AllFieldsSearch.and("domainId", AllFieldsSearch.entity().getDomainId(), Op.EQ); AllFieldsSearch.and("host", AllFieldsSearch.entity().getHostId(), Op.EQ); AllFieldsSearch.and("lastHost", AllFieldsSearch.entity().getLastHostId(), Op.EQ); @@ -337,10 +337,10 @@ public List listByNetworkAndPodAndRole(final long networkId, fin } @Override - public List listByNetworkAndRole(final long networkId, final Role role) { + public List listByNetworkAndRole(final long networkId, final Role... roles) { final SearchCriteria sc = AllFieldsSearch.create(); sc.setJoinParameters("networkRouter", "networkId", networkId); - sc.setParameters("role", role); + sc.setParameters("role", (Object[])roles); return listBy(sc); } diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index 5ff56a88fd2d..7306d60a53b4 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -4785,7 +4785,10 @@ private Pair patchSystemVm(VMInstanceVO systemVM, boolean force return new Pair<>(false, String.format("%s due to: %s", errMsg, e.getMessage())); } s_logger.info(String.format("Successfully patched system VM %s", systemVM.getInstanceName())); - if (systemVM.getType() == VirtualMachine.Type.DomainRouter) { + List routerTypes = new ArrayList<>(); + routerTypes.add(VirtualMachine.Type.DomainRouter); + routerTypes.add(VirtualMachine.Type.InternalLoadBalancerVm); + if (routerTypes.contains(systemVM.getType())) { boolean updated = updateRouterDetails(systemVM.getId(), answer.getScriptsVersion(), answer.getTemplateVersion()); if (!updated) { s_logger.warn("Failed to update router's script and template version details"); From 41e673855dce807c83a49392b6108353a0fe341d Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Wed, 6 Apr 2022 15:49:49 +0530 Subject: [PATCH 59/68] add unit tests for API param validations and new helper utilities - file scp & checksum validations --- .../admin/systemvm/PatchSystemVMCmd.java | 2 +- .../admin/systemvm/PatchSystemVMCmdTest.java | 66 ++++++++++++++++++ .../java/com/cloud/utils/FileUtilTest.java | 69 +++++++++++++++++++ .../utils/validation/ChecksumUtilTest.java | 62 +++++++++++++++++ 4 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 api/src/test/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmdTest.java create mode 100644 utils/src/test/java/com/cloud/utils/FileUtilTest.java create mode 100644 utils/src/test/java/com/cloud/utils/validation/ChecksumUtilTest.java diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java index 12699ba9b6c2..a0c066ce0e8f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java @@ -44,7 +44,7 @@ public class PatchSystemVMCmd extends BaseAsyncCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = SystemVmResponse.class, - description = "patches systemVM - CPVM/SSVM/Router with the specified ID") + description = "patches systemVM - CPVM/SSVM with the specified ID") private Long id; @Parameter(name = ApiConstants.FORCED, type = CommandType.BOOLEAN, diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmdTest.java new file mode 100644 index 000000000000..163edc41fe3d --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmdTest.java @@ -0,0 +1,66 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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.A +package org.apache.cloudstack.api.command.admin.systemvm; + +import com.cloud.server.ManagementService; +import com.cloud.utils.Pair; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.springframework.test.util.ReflectionTestUtils; + +public class PatchSystemVMCmdTest { + + @Mock + private ManagementService _mgr; + + @InjectMocks + PatchSystemVMCmd cmd = new PatchSystemVMCmd(); + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + } + + @Test + public void patchValidSystemVM() { + ReflectionTestUtils.setField(cmd, "id", 1L); + Pair successResponse = new Pair<>(true, ""); + Mockito.doReturn(successResponse).when(_mgr).patchSystemVM(cmd); + try { + cmd.execute(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void patchInvalidSystemVM() { + ReflectionTestUtils.setField(cmd, "id", null); + Pair failureResponse = new Pair<>(false, "Please provide a valid ID of a system VM to be patched"); + Mockito.doReturn(failureResponse).when(_mgr).patchSystemVM(cmd); + try { + cmd.execute(); + } catch (Exception e) { + Assert.assertEquals(failureResponse.second(), e.getMessage()); + } + } +} diff --git a/utils/src/test/java/com/cloud/utils/FileUtilTest.java b/utils/src/test/java/com/cloud/utils/FileUtilTest.java new file mode 100644 index 000000000000..70ad39cd5851 --- /dev/null +++ b/utils/src/test/java/com/cloud/utils/FileUtilTest.java @@ -0,0 +1,69 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.utils; + +import com.cloud.utils.ssh.SshHelper; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.io.File; + +import static org.mockito.ArgumentMatchers.nullable; + +@PrepareForTest(value = {SshHelper.class}) +@RunWith(PowerMockRunner.class) +@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.parsers.*", "javax.xml.*", "org.w3c.dom.*", "org.xml.*"}) +public class FileUtilTest { + + @Test + public void successfulScpTest() throws Exception { + PowerMockito.mockStatic(SshHelper.class); + String basePath = "/tmp"; + String[] files = new String[] { "file1.txt" }; + int sshPort = 3922; + String controlIp = "10.0.0.10"; + String destPath = "/home/cloud/"; + File pemFile = new File("/root/.ssh/id_rsa"); + PowerMockito.doNothing().when(SshHelper.class, "scpTo", Mockito.anyString(), Mockito.anyInt(), Mockito.anyString(), Mockito.any(File.class), nullable(String.class), Mockito.anyString(), Mockito.any(String[].class), Mockito.anyString()); + FileUtil.scpPatchFiles(controlIp, destPath, sshPort, pemFile, files, basePath); + } + + @Test + public void FailingScpFilesTest() throws Exception { + PowerMockito.mockStatic(SshHelper.class); + String basePath = "/tmp"; + String[] files = new String[] { "file1.txt" }; + int sshPort = 3922; + String controlIp = "10.0.0.10"; + String destPath = "/home/cloud/"; + File pemFile = new File("/root/.ssh/id_rsa"); + PowerMockito.doThrow(new Exception()).when(SshHelper.class, "scpTo", Mockito.anyString(), Mockito.anyInt(), Mockito.anyString(), Mockito.any(File.class), Mockito.anyString(), Mockito.anyString(), Mockito.any(String[].class), Mockito.anyString()); + try { + FileUtil.scpPatchFiles(controlIp, destPath, sshPort, pemFile, files, basePath); + } catch (Exception e) { + Assert.assertEquals("Failed to scp files to system VM", e.getMessage()); + } + + } + +} diff --git a/utils/src/test/java/com/cloud/utils/validation/ChecksumUtilTest.java b/utils/src/test/java/com/cloud/utils/validation/ChecksumUtilTest.java new file mode 100644 index 000000000000..08cc389621ee --- /dev/null +++ b/utils/src/test/java/com/cloud/utils/validation/ChecksumUtilTest.java @@ -0,0 +1,62 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 com.cloud.utils.validation; + +import com.cloud.utils.script.Script; +import org.apache.cloudstack.utils.security.DigestHelper; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.io.File; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +@PrepareForTest(value = {Script.class, DigestHelper.class}) +@RunWith(PowerMockRunner.class) +@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.parsers.*", "javax.xml.*", "org.w3c.dom.*", "org.xml.*"}) +public class ChecksumUtilTest { + + @Test + public void invalidFileForCheckSumValidationTest() { + PowerMockito.mockStatic(Script.class); + Mockito.when(Script.findScript(Mockito.anyString(), Mockito.anyString())).thenReturn(null); + try { + ChecksumUtil.calculateCurrentChecksum(Mockito.anyString(), Mockito.anyString()); + } catch (Exception e) { + assertTrue(e.getMessage().contains("Unable to find cloudScripts path, cannot update SystemVM")); + } + } + + @Test + public void generateChecksumTest() { + PowerMockito.mockStatic(Script.class); + PowerMockito.mockStatic(DigestHelper.class); + Mockito.when(Script.findScript(Mockito.anyString(), Mockito.anyString())).thenReturn("/dummyPath"); + Mockito.when(DigestHelper.calculateChecksum(Mockito.any(File.class))).thenReturn("dummy-checksum"); + try { + ChecksumUtil.calculateCurrentChecksum(Mockito.anyString(), Mockito.anyString()); + } catch (Exception e) { + fail("Failed to generate checksum"); + } + } +} From 06791f406c6efeffc22e3b81935f42b44f9e49e2 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Mon, 11 Apr 2022 11:46:32 +0530 Subject: [PATCH 60/68] perform patching only for non-user i.e., system VMs --- .../xenbase/CitrixStartCommandWrapper.java | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java index 7b1d6aeac6fd..d1b5224f28f2 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixStartCommandWrapper.java @@ -182,31 +182,33 @@ public Answer execute(final StartCommand command, final CitrixResourceBase citri state = VmPowerState.RUNNING; - String controlIp = null; - for (final NicTO nic : vmSpec.getNics()) { - if (nic.getType() == Networks.TrafficType.Control) { - controlIp = nic.getIp(); - break; + if (vmSpec.getType() != VirtualMachine.Type.User) { + String controlIp = null; + for (final NicTO nic : vmSpec.getNics()) { + if (nic.getType() == Networks.TrafficType.Control) { + controlIp = nic.getIp(); + break; + } } - } - String result2 = citrixResourceBase.connect(conn, vmName, controlIp, 1000); - if (StringUtils.isEmpty(result2)) { - s_logger.info(String.format("Connected to SystemVM: %s", vmName)); - } + String result2 = citrixResourceBase.connect(conn, vmName, controlIp, 1000); + if (StringUtils.isEmpty(result2)) { + s_logger.info(String.format("Connected to SystemVM: %s", vmName)); + } - try { - citrixResourceBase.copyPatchFilesToVR(controlIp, "/tmp/"); - VirtualRoutingResource vrResource = citrixResourceBase.getVirtualRoutingResource(); - if (!vrResource.isSystemVMSetup(vmName, controlIp)) { - String errMsg = "Failed to patch systemVM"; - s_logger.error(errMsg); - return new StartAnswer(command, errMsg); + try { + citrixResourceBase.copyPatchFilesToVR(controlIp, "/tmp/"); + VirtualRoutingResource vrResource = citrixResourceBase.getVirtualRoutingResource(); + if (!vrResource.isSystemVMSetup(vmName, controlIp)) { + String errMsg = "Failed to patch systemVM"; + s_logger.error(errMsg); + return new StartAnswer(command, errMsg); + } + } catch (Exception e) { + String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; + s_logger.error(errMsg, e); + return new StartAnswer(command, String.format("%s due to: %s", errMsg, e.getMessage())); } - } catch (Exception e) { - String errMsg = "Failed to scp files to system VM. Patching of systemVM failed"; - s_logger.error(errMsg, e); - return new StartAnswer(command, String.format("%s due to: %s", errMsg, e.getMessage())); } final StartAnswer startAnswer = new StartAnswer(command); From a12789d66f53ede13dc6c21d1edb610c2fb924ad Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Tue, 12 Apr 2022 11:45:10 +0530 Subject: [PATCH 61/68] add test to validate params --- .../admin/systemvm/PatchSystemVMCmdTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmdTest.java index 163edc41fe3d..cac2edba6dd0 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmdTest.java @@ -17,16 +17,28 @@ package org.apache.cloudstack.api.command.admin.systemvm; import com.cloud.server.ManagementService; +import com.cloud.user.Account; import com.cloud.utils.Pair; +import org.apache.cloudstack.context.CallContext; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; import org.springframework.test.util.ReflectionTestUtils; +import java.util.Optional; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(CallContext.class) +@PowerMockIgnore({"javax.xml.*", "org.w3c.dom.*", "org.apache.xerces.*", "org.xml.*"}) public class PatchSystemVMCmdTest { @Mock @@ -63,4 +75,20 @@ public void patchInvalidSystemVM() { Assert.assertEquals(failureResponse.second(), e.getMessage()); } } + + @Test + public void validateArgsForPatchSystemVMApi() { + PowerMockito.mockStatic(CallContext.class); + CallContext callContextMock = PowerMockito.mock(CallContext.class); + PowerMockito.when(CallContext.current()).thenReturn(callContextMock); + Account accountMock = PowerMockito.mock(Account.class); + PowerMockito.when(callContextMock.getCallingAccount()).thenReturn(accountMock); + Mockito.when(accountMock.getId()).thenReturn(2L); + ReflectionTestUtils.setField(cmd, "id", 1L); + Assert.assertEquals((long)cmd.getId(), 1L); + Assert.assertFalse(cmd.isForced()); + Assert.assertEquals(cmd.getEntityOwnerId(), 2L); + + + } } From e35d51d350b5c578e4623775e95b9601e4f91e9b Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Tue, 12 Apr 2022 14:06:03 +0530 Subject: [PATCH 62/68] remove unused import --- .../api/command/admin/systemvm/PatchSystemVMCmdTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmdTest.java index cac2edba6dd0..125c8b566658 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmdTest.java @@ -34,8 +34,6 @@ import org.powermock.modules.junit4.PowerMockRunner; import org.springframework.test.util.ReflectionTestUtils; -import java.util.Optional; - @RunWith(PowerMockRunner.class) @PrepareForTest(CallContext.class) @PowerMockIgnore({"javax.xml.*", "org.w3c.dom.*", "org.apache.xerces.*", "org.xml.*"}) From 8e9175b585021dc1ec01422a1075603992e96dee Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Tue, 19 Apr 2022 18:43:53 +0530 Subject: [PATCH 63/68] add column to domain_router to display software version and support networkrestart with livePatch from router view --- .../api/response/DomainRouterResponse.java | 12 ++++ .../java/com/cloud/vm/DomainRouterVO.java | 11 ++++ .../META-INF/db/schema-41610to41700.sql | 61 ++++++++++--------- .../query/dao/DomainRouterJoinDaoImpl.java | 1 + .../api/query/vo/DomainRouterJoinVO.java | 7 +++ .../cloud/server/ManagementServerImpl.java | 6 ++ ui/public/locales/en.json | 2 + ui/src/config/section/infra/ilbvms.js | 4 +- ui/src/config/section/infra/routers.js | 30 ++++++++- ui/src/views/AutogenView.vue | 4 +- 10 files changed, 104 insertions(+), 34 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/response/DomainRouterResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/DomainRouterResponse.java index 66f403074493..a5fa2bd08c2a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/DomainRouterResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/DomainRouterResponse.java @@ -233,6 +233,10 @@ public class DomainRouterResponse extends BaseResponseWithAnnotations implements @Param(description = "Last executed health check result for the router", responseObject = RouterHealthCheckResultResponse.class, since = "4.14") List healthCheckResults; + @SerializedName("softwareversion") + @Param(description = "the version of the code / software in the router") + private String softwareVersion; + public DomainRouterResponse() { nics = new LinkedHashSet(); } @@ -490,4 +494,12 @@ public void setHealthChecksFailed(boolean healthChecksFailed) { public void setHealthCheckResults(List healthCheckResults) { this.healthCheckResults = healthCheckResults; } + + public String getSoftwareVersion() { + return softwareVersion; + } + + public void setSoftwareVersion(String softwareVersion) { + this.softwareVersion = softwareVersion; + } } diff --git a/engine/schema/src/main/java/com/cloud/vm/DomainRouterVO.java b/engine/schema/src/main/java/com/cloud/vm/DomainRouterVO.java index 8bd973af531c..1a619734ff39 100644 --- a/engine/schema/src/main/java/com/cloud/vm/DomainRouterVO.java +++ b/engine/schema/src/main/java/com/cloud/vm/DomainRouterVO.java @@ -74,6 +74,9 @@ public class DomainRouterVO extends VMInstanceVO implements VirtualRouter { @Enumerated(EnumType.STRING) private UpdateState updateState; + @Column(name= "software_version") + private String softwareVersion; + public DomainRouterVO(final long id, final long serviceOfferingId, final long elementId, final String name, final long templateId, final HypervisorType hypervisorType, final long guestOSId, final long domainId, final long accountId, final long userId, final boolean isRedundantRouter, final RedundantState redundantState, final boolean haEnabled, final boolean stopPending, final Long vpcId) { @@ -211,4 +214,12 @@ public void setUpdateState(UpdateState updateState) { public String getName() { return instanceName; } + + public String getSoftwareVersion() { + return softwareVersion; + } + + public void setSoftwareVersion(String softwareVersion) { + this.softwareVersion = softwareVersion; + } } diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41610to41700.sql b/engine/schema/src/main/resources/META-INF/db/schema-41610to41700.sql index 15a589da4472..cb6d729f9c40 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-41610to41700.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-41610to41700.sql @@ -539,6 +539,35 @@ FROM LEFT JOIN `user_vm_details` `custom_ram_size` ON (((`custom_ram_size`.`vm_id` = `vm_instance`.`id`) AND (`custom_ram_size`.`name` = 'memory')))); +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) SELECT UUID(), 3, 'listConfigurations', 'ALLOW', (SELECT MAX(`sort_order`)+1 FROM `cloud`.`role_permissions`) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) SELECT UUID(), 3, 'updateConfiguration', 'ALLOW', (SELECT MAX(`sort_order`)+1 FROM `cloud`.`role_permissions`) ON DUPLICATE KEY UPDATE rule=rule; + +INSERT INTO `cloud`.`user_vm_details`(`vm_id`, `name`, `value`) + SELECT `user_vm_details`.`vm_id`, 'SSH.KeyPairNames', `ssh_keypairs`.`keypair_name` + FROM `cloud`.`user_vm_details` + INNER JOIN `cloud`.`ssh_keypairs` ON ssh_keypairs.public_key = user_vm_details.value + INNER JOIN `cloud`.`vm_instance` ON vm_instance.id = user_vm_details.vm_id + WHERE ssh_keypairs.account_id = vm_instance.account_id; + +ALTER TABLE `cloud`.`kubernetes_cluster` ADD COLUMN `security_group_id` bigint unsigned DEFAULT NULL, +ADD CONSTRAINT `fk_kubernetes_cluster__security_group_id` FOREIGN KEY `fk_kubernetes_cluster__security_group_id`(`security_group_id`) REFERENCES `security_group`(`id`) ON DELETE CASCADE; + +-- PR#5984 Create table to persist VM stats. +DROP TABLE IF EXISTS `cloud`.`vm_stats`; +CREATE TABLE `cloud`.`vm_stats` ( + `id` bigint unsigned NOT NULL auto_increment COMMENT 'id', + `vm_id` bigint unsigned NOT NULL, + `mgmt_server_id` bigint unsigned NOT NULL, + `timestamp` datetime NOT NULL, + `vm_stats_data` text NOT NULL, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- PR#5984 Update name for global configuration vm.stats.increment.metrics +Update configuration set name='vm.stats.increment.metrics' where name='vm.stats.increment.metrics.in.memory'; + +ALTER TABLE `cloud`.`domain_router` ADD COLUMN `software_version` varchar(100) COMMENT 'Software version'; + DROP VIEW IF EXISTS `cloud`.`domain_router_view`; CREATE VIEW `cloud`.`domain_router_view` AS select @@ -610,7 +639,8 @@ CREATE VIEW `cloud`.`domain_router_view` AS domain_router.is_redundant_router is_redundant_router, domain_router.redundant_state redundant_state, domain_router.stop_pending stop_pending, - domain_router.role role + domain_router.role role, + domain_router.software_version software_version from `cloud`.`domain_router` inner join @@ -640,31 +670,4 @@ CREATE VIEW `cloud`.`domain_router_view` AS left join `cloud`.`async_job` ON async_job.instance_id = vm_instance.id and async_job.instance_type = 'DomainRouter' - and async_job.job_status = 0; - -INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) SELECT UUID(), 3, 'listConfigurations', 'ALLOW', (SELECT MAX(`sort_order`)+1 FROM `cloud`.`role_permissions`) ON DUPLICATE KEY UPDATE rule=rule; -INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) SELECT UUID(), 3, 'updateConfiguration', 'ALLOW', (SELECT MAX(`sort_order`)+1 FROM `cloud`.`role_permissions`) ON DUPLICATE KEY UPDATE rule=rule; - -INSERT INTO `cloud`.`user_vm_details`(`vm_id`, `name`, `value`) - SELECT `user_vm_details`.`vm_id`, 'SSH.KeyPairNames', `ssh_keypairs`.`keypair_name` - FROM `cloud`.`user_vm_details` - INNER JOIN `cloud`.`ssh_keypairs` ON ssh_keypairs.public_key = user_vm_details.value - INNER JOIN `cloud`.`vm_instance` ON vm_instance.id = user_vm_details.vm_id - WHERE ssh_keypairs.account_id = vm_instance.account_id; - -ALTER TABLE `cloud`.`kubernetes_cluster` ADD COLUMN `security_group_id` bigint unsigned DEFAULT NULL, -ADD CONSTRAINT `fk_kubernetes_cluster__security_group_id` FOREIGN KEY `fk_kubernetes_cluster__security_group_id`(`security_group_id`) REFERENCES `security_group`(`id`) ON DELETE CASCADE; - --- PR#5984 Create table to persist VM stats. -DROP TABLE IF EXISTS `cloud`.`vm_stats`; -CREATE TABLE `cloud`.`vm_stats` ( - `id` bigint unsigned NOT NULL auto_increment COMMENT 'id', - `vm_id` bigint unsigned NOT NULL, - `mgmt_server_id` bigint unsigned NOT NULL, - `timestamp` datetime NOT NULL, - `vm_stats_data` text NOT NULL, - PRIMARY KEY (`id`) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- PR#5984 Update name for global configuration vm.stats.increment.metrics -Update configuration set name='vm.stats.increment.metrics' where name='vm.stats.increment.metrics.in.memory'; + and async_job.job_status = 0; \ No newline at end of file diff --git a/server/src/main/java/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java index 0ed234c51e10..839db53eff30 100644 --- a/server/src/main/java/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java @@ -90,6 +90,7 @@ public DomainRouterResponse newDomainRouterResponse(DomainRouterJoinVO router, A routerResponse.setState(router.getState()); routerResponse.setIsRedundantRouter(router.isRedundantRouter()); routerResponse.setScriptsVersion(router.getScriptsVersion()); + routerResponse.setSoftwareVersion(router.getSoftwareVersion()); if (router.getRedundantState() != null) { routerResponse.setRedundantState(router.getRedundantState().toString()); } diff --git a/server/src/main/java/com/cloud/api/query/vo/DomainRouterJoinVO.java b/server/src/main/java/com/cloud/api/query/vo/DomainRouterJoinVO.java index c29f9b5e2cb8..51171ff6913a 100644 --- a/server/src/main/java/com/cloud/api/query/vo/DomainRouterJoinVO.java +++ b/server/src/main/java/com/cloud/api/query/vo/DomainRouterJoinVO.java @@ -251,6 +251,9 @@ public class DomainRouterJoinVO extends BaseViewVO implements ControlledViewEnti @Enumerated(value = EnumType.STRING) private VirtualRouter.Role role; + @Column(name = "software_version") + private String softwareVersion; + public DomainRouterJoinVO() { } @@ -534,4 +537,8 @@ public VirtualRouter.Role getRole() { public Class getEntityType() { return VirtualMachine.class; } + + public String getSoftwareVersion() { + return softwareVersion; + } } diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index e4de22648fcc..a3fdbc74086e 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -595,6 +595,7 @@ import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao; import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO; +import org.apache.cloudstack.utils.CloudStackVersion; import org.apache.cloudstack.utils.identity.ManagementServerNode; import org.apache.commons.codec.binary.Base64; import org.apache.commons.collections.CollectionUtils; @@ -4781,6 +4782,11 @@ private boolean updateRouterDetails(Long routerId, String scriptVersion, String router.setTemplateVersion(templateVersion); router.setScriptsVersion(scriptVersion); + String codeVersion = getVersion(); + if (StringUtils.isNotEmpty(codeVersion)) { + codeVersion = CloudStackVersion.parse(codeVersion).toString(); + } + router.setSoftwareVersion(codeVersion); return routerDao.update(routerId, router); } diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 821ef154f4e5..5628368ff2be 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -2078,6 +2078,7 @@ "label.snmpcommunity": "SNMP Community", "label.snmpport": "SNMP Port", "label.sockettimeout": "Socket Timeout", +"label.softwareversion": "Software Version", "label.source.based": "SourceBased", "label.source.nat.supported": "SourceNAT Supported", "label.sourcecidr": "Source CIDR", @@ -2576,6 +2577,7 @@ "message.action.host.enable.maintenance.mode": "Enabling maintenance mode will cause a live migration of all running instances on this host to any available host.", "message.action.instance.reset.password": "Please confirm that you want to change the ROOT password for this virtual machine.", "message.action.manage.cluster": "Please confirm that you want to manage the cluster.", +"message.action.patch.router": "Please confirm that you want to live patch the router.
This operation is equivalent updating the router packages and restarting the network without cleanup.", "message.action.patch.systemvm": "Please confirm that you want to patch the System VM.", "message.action.primarystorage.enable.maintenance.mode": "Warning: placing the primary storage into maintenance mode will cause all VMs using volumes from it to be stopped. Do you want to continue?", "message.action.reboot.instance": "Please confirm that you want to reboot this instance.", diff --git a/ui/src/config/section/infra/ilbvms.js b/ui/src/config/section/infra/ilbvms.js index b09d3092ce22..1c27a960af65 100644 --- a/ui/src/config/section/infra/ilbvms.js +++ b/ui/src/config/section/infra/ilbvms.js @@ -22,8 +22,8 @@ export default { icon: 'share-alt-outlined', permission: ['listInternalLoadBalancerVMs'], params: { projectid: '-1' }, - columns: ['name', 'state', 'publicip', 'guestnetworkname', 'vpcname', 'version', 'hostname', 'account', 'zonename', 'requiresupgrade'], - details: ['name', 'id', 'version', 'requiresupgrade', 'guestnetworkname', 'vpcname', 'publicip', 'guestipaddress', 'linklocalip', 'serviceofferingname', 'networkdomain', 'isredundantrouter', 'redundantstate', 'hostname', 'account', 'zonename', 'created'], + columns: ['name', 'state', 'publicip', 'guestnetworkname', 'vpcname', 'version', 'softwareversion', 'hostname', 'account', 'zonename', 'requiresupgrade'], + details: ['name', 'id', 'version', 'softwareversion', 'requiresupgrade', 'guestnetworkname', 'vpcname', 'publicip', 'guestipaddress', 'linklocalip', 'serviceofferingname', 'networkdomain', 'isredundantrouter', 'redundantstate', 'hostname', 'account', 'zonename', 'created'], actions: [ { api: 'startInternalLoadBalancerVM', diff --git a/ui/src/config/section/infra/routers.js b/ui/src/config/section/infra/routers.js index 77c9d3d851fa..b92209782658 100644 --- a/ui/src/config/section/infra/routers.js +++ b/ui/src/config/section/infra/routers.js @@ -24,9 +24,9 @@ export default { docHelp: 'adminguide/systemvm.html#virtual-router', permission: ['listRouters'], params: { projectid: '-1' }, - columns: ['name', 'state', 'publicip', 'guestnetworkname', 'vpcname', 'redundantstate', 'version', 'hostname', 'account', 'zonename', 'requiresupgrade'], + columns: ['name', 'state', 'publicip', 'guestnetworkname', 'vpcname', 'redundantstate', 'version', 'softwareversion', 'hostname', 'account', 'zonename', 'requiresupgrade'], searchFilters: ['name', 'zoneid', 'podid', 'clusterid'], - details: ['name', 'id', 'version', 'requiresupgrade', 'guestnetworkname', 'vpcname', 'publicip', 'guestipaddress', 'linklocalip', 'serviceofferingname', 'networkdomain', 'isredundantrouter', 'redundantstate', 'hostname', 'account', 'zonename', 'created'], + details: ['name', 'id', 'version', 'softwareversion', 'requiresupgrade', 'guestnetworkname', 'vpcname', 'publicip', 'guestipaddress', 'linklocalip', 'serviceofferingname', 'networkdomain', 'isredundantrouter', 'redundantstate', 'hostname', 'account', 'zonename', 'created'], resourceType: 'VirtualRouter', tabs: [{ name: 'details', @@ -84,6 +84,32 @@ export default { popup: true, groupMap: (selection, values) => { return selection.map(x => { return { id: x, forced: values.forced } }) } }, + { + api: 'restartNetwork', + icon: 'diff-outlined', + label: 'label.action.patch.systemvm', + message: 'message.action.patch.router', + dataView: true, + hidden: (record) => { return record.state === 'Running' }, + mapping: { + id: { + value: (record) => { return record.guestnetworkid } + }, + livepatch: { + value: (record) => { return true } + } + }, + groupAction: true, + popup: true, + groupMap: (selection, values, record) => { + return selection.map(x => { + const data = record.filter(y => { return y.id === x }) + return { + id: data[0].guestnetworkid, livepatch: true + } + }) + } + }, { api: 'scaleSystemVm', icon: 'arrows-alt-outlined', diff --git a/ui/src/views/AutogenView.vue b/ui/src/views/AutogenView.vue index 69eea6b6e4a1..3bec016000df 100644 --- a/ui/src/views/AutogenView.vue +++ b/ui/src/views/AutogenView.vue @@ -589,6 +589,8 @@ export default { var objIndex = 0 if (this.$route.path.includes('/template') || this.$route.path.includes('/iso')) { objIndex = selectedItems.findIndex(obj => (obj.zoneid === tempResource[r])) + } else if (this.$route.path.includes('/router')) { + objIndex = selectedItems.findIndex(obj => (obj.guestnetworkid === tempResource[r])) } else { objIndex = selectedItems.findIndex(obj => (obj.id === tempResource[r] || obj.username === tempResource[r])) } @@ -1261,7 +1263,7 @@ export default { this.items.map(x => { itemsNameMap[x.id] = x.name || x.displaytext || x.id }) - const paramsList = this.currentAction.groupMap(this.selectedRowKeys, values) + const paramsList = this.currentAction.groupMap(this.selectedRowKeys, values, this.items) for (const params of paramsList) { var resourceName = itemsNameMap[params.id] // Using a method for this since it's an async call and don't want wrong prarms to be passed From 30c00e68e96711c50882e637edfa8117527c0874 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Wed, 20 Apr 2022 11:28:35 +0530 Subject: [PATCH 64/68] Requires upgrade column to consider package (cloud-scripts) checksum to identify if true/false --- .../api/query/dao/DomainRouterJoinDaoImpl.java | 16 +++++++++++++++- .../com/cloud/network/router/NetworkHelper.java | 1 + .../cloud/network/router/NetworkHelperImpl.java | 14 ++++++++++++++ .../VirtualNetworkApplianceManagerImpl.java | 10 +++++++++- ui/public/locales/en.json | 1 + ui/src/components/view/ListView.vue | 3 +++ ui/src/config/section/infra/routers.js | 10 +++++++--- 7 files changed, 50 insertions(+), 5 deletions(-) diff --git a/server/src/main/java/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java index 839db53eff30..97c7675bbccc 100644 --- a/server/src/main/java/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java @@ -21,9 +21,11 @@ import javax.inject.Inject; +import com.cloud.utils.validation.ChecksumUtil; import org.apache.cloudstack.annotation.AnnotationService; import org.apache.cloudstack.annotation.dao.AnnotationDao; import org.apache.cloudstack.context.CallContext; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -97,7 +99,19 @@ public DomainRouterResponse newDomainRouterResponse(DomainRouterJoinVO router, A if (router.getTemplateVersion() != null) { String routerVersion = CloudStackVersion.trimRouterVersion(router.getTemplateVersion()); routerResponse.setVersion(routerVersion); - routerResponse.setRequiresUpgrade((CloudStackVersion.compare(routerVersion, NetworkOrchestrationService.MinVRVersion.valueIn(router.getDataCenterId())) < 0)); + boolean isTempVersionLower = (CloudStackVersion.compare(routerVersion, NetworkOrchestrationService.MinVRVersion.valueIn(router.getDataCenterId())) < 0); + if (!isTempVersionLower) { + routerResponse.setRequiresUpgrade(false); + } else { + String currentCheckSum = ChecksumUtil.calculateCurrentChecksum(router.getName(), "vms/cloud-scripts.tgz").trim().replaceAll("\n",""); + String routerScriptVersion = router.getScriptsVersion(); + boolean requiresUpgrade = true; + if (StringUtils.isNotEmpty(routerScriptVersion)) { + routerScriptVersion = routerScriptVersion.trim().replaceAll("\n", ""); + requiresUpgrade = !(routerScriptVersion.equals(currentCheckSum)); + } + routerResponse.setRequiresUpgrade(requiresUpgrade); + } } else { routerResponse.setVersion("UNKNOWN"); routerResponse.setRequiresUpgrade(true); diff --git a/server/src/main/java/com/cloud/network/router/NetworkHelper.java b/server/src/main/java/com/cloud/network/router/NetworkHelper.java index 9e4a5571b44e..ea008e4c4ca0 100644 --- a/server/src/main/java/com/cloud/network/router/NetworkHelper.java +++ b/server/src/main/java/com/cloud/network/router/NetworkHelper.java @@ -65,6 +65,7 @@ public abstract VirtualRouter destroyRouter(long routerId, Account caller, * @return */ public abstract boolean checkRouterVersion(VirtualRouter router); + public abstract boolean checkRouterTemplateVersion(VirtualRouter router); public abstract List startRouters( RouterDeploymentDefinition routerDeploymentDefinition) diff --git a/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java b/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java index 462b364142c1..d9e0833b8968 100644 --- a/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java +++ b/server/src/main/java/com/cloud/network/router/NetworkHelperImpl.java @@ -289,6 +289,20 @@ public boolean checkRouterVersion(final VirtualRouter router) { return routerCheckSumMatch; } + @Override + public boolean checkRouterTemplateVersion(final VirtualRouter router) { + if (!VirtualNetworkApplianceManager.RouterVersionCheckEnabled.value()) { + // Router version check is disabled. + return true; + } + if (router.getTemplateVersion() == null) { + return false; + } + final long dcid = router.getDataCenterId(); + String routerVersion = CloudStackVersion.trimRouterVersion(router.getTemplateVersion()); + return CloudStackVersion.compare(routerVersion, NetworkOrchestrationService.MinVRVersion.valueIn(dcid)) >= 0; + } + protected DomainRouterVO start(DomainRouterVO router, final User user, final Account caller, final Map params, final DeploymentPlan planToDeploy) throws StorageUnavailableException, InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { s_logger.debug("Starting router " + router); diff --git a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index b9a7008e33ea..cd676aa62925 100644 --- a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -46,6 +46,7 @@ import javax.naming.ConfigurationException; import com.cloud.offering.DiskOffering; +import com.cloud.server.ManagementServer; import org.apache.cloudstack.alert.AlertService; import org.apache.cloudstack.alert.AlertService.AlertType; import org.apache.cloudstack.api.command.admin.router.RebootRouterCmd; @@ -66,6 +67,7 @@ import org.apache.cloudstack.network.router.deployment.RouterDeploymentDefinitionBuilder; import org.apache.cloudstack.network.topology.NetworkTopology; import org.apache.cloudstack.network.topology.NetworkTopologyContext; +import org.apache.cloudstack.utils.CloudStackVersion; import org.apache.cloudstack.utils.identity.ManagementServerNode; import org.apache.cloudstack.utils.usage.UsageUtils; import org.apache.commons.lang3.StringUtils; @@ -364,6 +366,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V @Inject protected CommandSetupHelper _commandSetupHelper; @Inject protected RouterDeploymentDefinitionBuilder _routerDeploymentManagerBuilder; + @Inject private ManagementServer mgr; private int _routerRamSize; private int _routerCpuMHz; @@ -2679,6 +2682,11 @@ public boolean finalizeStart(final VirtualMachineProfile profile, final long hos final GetDomRVersionAnswer versionAnswer = (GetDomRVersionAnswer) cmds.getAnswer("getDomRVersion"); router.setTemplateVersion(versionAnswer.getTemplateVersion()); router.setScriptsVersion(versionAnswer.getScriptsVersion()); + String codeVersion = mgr.getVersion(); + if (StringUtils.isNotEmpty(codeVersion)) { + codeVersion = CloudStackVersion.parse(codeVersion).toString(); + } + router.setSoftwareVersion(codeVersion); _routerDao.persist(router, guestNetworks); final List routerNics = _nicDao.listByVmId(profile.getId()); @@ -3209,7 +3217,7 @@ public List upgradeRouterTemplate(final UpgradeRouterTemplateCmd cmd) { private List rebootRouters(final List routers) { final List jobIds = new ArrayList(); for (final DomainRouterVO router : routers) { - if (!_nwHelper.checkRouterVersion(router)) { + if (!_nwHelper.checkRouterTemplateVersion(router)) { s_logger.debug("Upgrading template for router: " + router.getId()); final Map params = new HashMap(); params.put("ctxUserId", "1"); diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 06bcc0e7c1e3..2db966de86bd 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -2226,6 +2226,7 @@ "label.templatesubject": "Subject", "label.templatetotal": "Template", "label.templatetype": "Template Type", +"label.templateversion": "Template Version", "label.tftp.dir": "TFTP Directory", "label.tftpdir": "Tftp root directory", "label.theme.alert": "The setting is only visible to the current browser. To apply the setting, please download the JSON file and replace its content in the `theme` section of the `config.json` file under the path: `/public/config.json`", diff --git a/ui/src/components/view/ListView.vue b/ui/src/components/view/ListView.vue index 7899d88fb2ae..858d32d39243 100644 --- a/ui/src/components/view/ListView.vue +++ b/ui/src/components/view/ListView.vue @@ -288,6 +288,9 @@ {{ text }} {{ text }} + diff --git a/ui/src/config/section/infra/routers.js b/ui/src/config/section/infra/routers.js index b92209782658..cf5145637ed5 100644 --- a/ui/src/config/section/infra/routers.js +++ b/ui/src/config/section/infra/routers.js @@ -24,7 +24,11 @@ export default { docHelp: 'adminguide/systemvm.html#virtual-router', permission: ['listRouters'], params: { projectid: '-1' }, - columns: ['name', 'state', 'publicip', 'guestnetworkname', 'vpcname', 'redundantstate', 'version', 'softwareversion', 'hostname', 'account', 'zonename', 'requiresupgrade'], + columns: () => { + var columns = ['name', 'state', 'publicip', 'guestnetworkname', 'vpcname', 'redundantstate', 'softwareversion', 'hostname', 'account', 'zonename', 'requiresupgrade'] + columns.splice(6, 0, { field: 'version', customTitle: 'templateversion' }) + return columns + }, searchFilters: ['name', 'zoneid', 'podid', 'clusterid'], details: ['name', 'id', 'version', 'softwareversion', 'requiresupgrade', 'guestnetworkname', 'vpcname', 'publicip', 'guestipaddress', 'linklocalip', 'serviceofferingname', 'networkdomain', 'isredundantrouter', 'redundantstate', 'hostname', 'account', 'zonename', 'created'], resourceType: 'VirtualRouter', @@ -138,8 +142,8 @@ export default { message: 'message.confirm.upgrade.router.newer.template', docHelp: 'adminguide/systemvm.html#upgrading-virtual-routers', dataView: true, - groupAction: true, - show: (record) => { return record.requiresupgrade } + groupAction: true + // show: (record) => { return record.requiresupgrade } }, { api: 'migrateSystemVm', From 47693fdce37185f0f015aff583e4456bb7a20ebc Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Wed, 20 Apr 2022 17:52:06 +0530 Subject: [PATCH 65/68] use router software version instead of checksum --- .../api/query/dao/DomainRouterJoinDaoImpl.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/server/src/main/java/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java index 97c7675bbccc..70a20c647419 100644 --- a/server/src/main/java/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java @@ -21,7 +21,6 @@ import javax.inject.Inject; -import com.cloud.utils.validation.ChecksumUtil; import org.apache.cloudstack.annotation.AnnotationService; import org.apache.cloudstack.annotation.dao.AnnotationDao; import org.apache.cloudstack.context.CallContext; @@ -103,12 +102,14 @@ public DomainRouterResponse newDomainRouterResponse(DomainRouterJoinVO router, A if (!isTempVersionLower) { routerResponse.setRequiresUpgrade(false); } else { - String currentCheckSum = ChecksumUtil.calculateCurrentChecksum(router.getName(), "vms/cloud-scripts.tgz").trim().replaceAll("\n",""); - String routerScriptVersion = router.getScriptsVersion(); boolean requiresUpgrade = true; - if (StringUtils.isNotEmpty(routerScriptVersion)) { - routerScriptVersion = routerScriptVersion.trim().replaceAll("\n", ""); - requiresUpgrade = !(routerScriptVersion.equals(currentCheckSum)); + String currentCodeVersion = this.getClass().getPackage().getImplementationVersion(); + if (StringUtils.isNotEmpty(currentCodeVersion)) { + currentCodeVersion = CloudStackVersion.parse(currentCodeVersion).toString(); + String routerSoftwareVersion = router.getSoftwareVersion(); + if (StringUtils.isNotEmpty(routerSoftwareVersion)) { + requiresUpgrade = !(currentCodeVersion.equals(routerSoftwareVersion)); + } } routerResponse.setRequiresUpgrade(requiresUpgrade); } From 75b46b2552174d1431654ef29ccbef2525fdddc1 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Wed, 20 Apr 2022 19:12:06 +0530 Subject: [PATCH 66/68] show N/A if no software version reported i.e., in upgraded envs --- ui/src/components/view/ListView.vue | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ui/src/components/view/ListView.vue b/ui/src/components/view/ListView.vue index 858d32d39243..31456bf30e78 100644 --- a/ui/src/components/view/ListView.vue +++ b/ui/src/components/view/ListView.vue @@ -291,6 +291,9 @@ + From cec9c82bb5c2cb88596bf7850cd1aed17807e5a5 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Wed, 20 Apr 2022 23:40:05 +0530 Subject: [PATCH 67/68] fix deb failure --- debian/cloudstack-common.install | 1 + debian/rules | 1 + 2 files changed, 2 insertions(+) diff --git a/debian/cloudstack-common.install b/debian/cloudstack-common.install index 8991abd02042..08f56d4f117f 100644 --- a/debian/cloudstack-common.install +++ b/debian/cloudstack-common.install @@ -28,6 +28,7 @@ /usr/share/cloudstack-common/scripts/vm/hypervisor/vmware/* /usr/share/cloudstack-common/scripts/vm/hypervisor/xenserver/* /usr/share/cloudstack-common/lib/* +/usr/share/cloudstack-common/vms/* /usr/bin/cloudstack-set-guest-password /usr/bin/cloudstack-set-guest-sshkey /usr/share/pyshared diff --git a/debian/rules b/debian/rules index dc74d991547c..7537e07a6b6b 100755 --- a/debian/rules +++ b/debian/rules @@ -123,6 +123,7 @@ override_dh_auto_install: cp -r scripts/storage $(DESTDIR)/usr/share/$(PACKAGE)-common/scripts cp -r scripts/util $(DESTDIR)/usr/share/$(PACKAGE)-common/scripts cp -r scripts/vm $(DESTDIR)/usr/share/$(PACKAGE)-common/scripts + cp -r systemvm/dist/* $(DESTDIR)/usr/share/$(PACKAGE)-common/vms install -D client/target/utilities/bin/cloud-migrate-databases $(DESTDIR)/usr/bin/cloudstack-migrate-databases install -D client/target/utilities/bin/cloud-set-guest-password $(DESTDIR)/usr/bin/cloudstack-set-guest-password install -D client/target/utilities/bin/cloud-set-guest-sshkey $(DESTDIR)/usr/bin/cloudstack-set-guest-sshkey From de0ce15907bf64f75b288de6c5b9d7d631a3a582 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Thu, 21 Apr 2022 21:07:22 +0530 Subject: [PATCH 68/68] update pom to official links of systemVM template --- engine/schema/pom.xml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/engine/schema/pom.xml b/engine/schema/pom.xml index 54999fc34a61..7dabcc2c0332 100644 --- a/engine/schema/pom.xml +++ b/engine/schema/pom.xml @@ -122,8 +122,7 @@ wget - - https://download.cloudstack.org/testing/systemvmtemplate/${cs.version}/md5sum.txt + https://download.cloudstack.org/systemvm/${cs.version}/md5sum.txt ${basedir}/dist/systemvm-templates/ true true @@ -182,8 +181,7 @@ true - - https://download.cloudstack.org/testing/systemvmtemplate/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-kvm.qcow2.bz2 + https://download.cloudstack.org/systemvm/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-kvm.qcow2.bz2 ${basedir}/dist/systemvm-templates/ ${kvm.checksum} @@ -219,8 +217,7 @@ true - - https://download.cloudstack.org/testing/systemvmtemplate/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-vmware.ova + https://download.cloudstack.org/systemvm/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-vmware.ova ${basedir}/dist/systemvm-templates/ ${vmware.checksum} @@ -256,8 +253,7 @@ true - - https://download.cloudstack.org/testing/systemvmtemplate/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-xen.vhd.bz2 + https://download.cloudstack.org/systemvm/${cs.version}/systemvmtemplate-${cs.version}.${patch.version}-xen.vhd.bz2 ${basedir}/dist/systemvm-templates/ ${xen.checksum}