You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by nv...@apache.org on 2021/09/15 03:26:39 UTC

[cloudstack] branch main updated: api: Update DNS on changing VM name (#5425)

This is an automated email from the ASF dual-hosted git repository.

nvazquez pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/main by this push:
     new f409e7a  api: Update DNS on changing VM name (#5425)
f409e7a is described below

commit f409e7a922fceeddcbb6c03d42b1a12410f182e0
Author: Pearl Dsilva <pe...@gmail.com>
AuthorDate: Wed Sep 15 08:56:12 2021 +0530

    api: Update DNS on changing VM name (#5425)
    
    * api: Update DNS on changing VM name
    
    * refactor backend code + UI - add warning messaging to prompt users to restart VM in case particular fields are updated
    
    * address comments
---
 .../main/java/com/cloud/vm/UserVmManagerImpl.java  | 59 +++++++++++++++++++---
 ui/public/locales/en.json                          |  1 +
 ui/src/config/section/compute.js                   |  1 -
 ui/src/views/compute/EditVM.vue                    |  3 ++
 4 files changed, 57 insertions(+), 7 deletions(-)

diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
index d3a67a0..72cd6f3 100644
--- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
@@ -50,6 +50,8 @@ import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
+import com.cloud.network.router.CommandSetupHelper;
+import com.cloud.network.router.NetworkHelper;
 import org.apache.cloudstack.acl.ControlledEntity;
 import org.apache.cloudstack.acl.ControlledEntity.ACLType;
 import org.apache.cloudstack.acl.SecurityChecker.AccessType;
@@ -116,6 +118,8 @@ import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
@@ -536,6 +540,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
     private BackupManager backupManager;
     @Inject
     private AnnotationDao annotationDao;
+    @Inject
+    protected CommandSetupHelper commandSetupHelper;
+    @Autowired
+    @Qualifier("networkHelper")
+    protected NetworkHelper nwHelper;
 
     private ScheduledExecutorService _executor = null;
     private ScheduledExecutorService _vmIpFetchExecutor = null;
@@ -2903,17 +2912,55 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
         _vmDao.updateVM(id, displayName, ha, osTypeId, userData, isDisplayVmEnabled, isDynamicallyScalable, customId, hostName, instanceName);
 
         if (updateUserdata) {
-            boolean result = updateUserDataInternal(_vmDao.findById(id));
-            if (result) {
-                s_logger.debug("User data successfully updated for vm id=" + id);
-            } else {
-                throw new CloudRuntimeException("Failed to reset userdata for the virtual machine ");
-            }
+            updateUserData(vm);
+        }
+
+        if (State.Running == vm.getState()) {
+            updateDns(vm, hostName);
         }
 
         return _vmDao.findById(id);
     }
 
+    private void updateUserData(UserVm vm) throws ResourceUnavailableException, InsufficientCapacityException {
+        boolean result = updateUserDataInternal(vm);
+        if (result) {
+            s_logger.debug(String.format("User data successfully updated for vm id:  %s", vm.getId()));
+        } else {
+            throw new CloudRuntimeException("Failed to reset userdata for the virtual machine ");
+        }
+    }
+
+    private void updateDns(UserVmVO vm, String hostName) throws ResourceUnavailableException, InsufficientCapacityException {
+        if (!StringUtils.isEmpty(hostName)) {
+            vm.setHostName(hostName);
+            try {
+                List<NicVO> nicVOs = _nicDao.listByVmId(vm.getId());
+                for (NicVO nic : nicVOs) {
+                    List<DomainRouterVO> routers = _routerDao.findByNetwork(nic.getNetworkId());
+                    for (DomainRouterVO router : routers) {
+                        if (router.getState() != State.Running) {
+                            s_logger.warn(String.format("Unable to update DNS for VM %s, as virtual router: %s is not in the right state: %s ", vm, router.getName(), router.getState()));
+                            continue;
+                        }
+                        Commands commands = new Commands(Command.OnError.Stop);
+                        commandSetupHelper.createDhcpEntryCommand(router, vm, nic, false, commands);
+                        if (!nwHelper.sendCommandsToRouter(router, commands)) {
+                            throw new CloudRuntimeException(String.format("Unable to send commands to virtual router: %s", router.getHostId()));
+                        }
+                        Answer answer = commands.getAnswer("dhcp");
+                        if (answer == null || !answer.getResult()) {
+                            throw new CloudRuntimeException("Failed to update hostname");
+                        }
+                        updateUserData(vm);
+                    }
+                }
+            } catch (CloudRuntimeException e) {
+                throw new CloudRuntimeException(String.format("Failed to update hostname of VM %s to %s", vm.getInstanceName(), vm.getHostName()));
+            }
+        }
+    }
+
     private boolean updateUserDataInternal(UserVm vm) throws ResourceUnavailableException, InsufficientCapacityException {
         VMTemplateVO template = _templateDao.findByIdIncludingRemoved(vm.getTemplateId());
 
diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json
index 90fcad8..a2e8cb3 100644
--- a/ui/public/locales/en.json
+++ b/ui/public/locales/en.json
@@ -3170,6 +3170,7 @@
 "message.restart.mgmt.server": "Please restart your management server(s) for your new settings to take effect.",
 "message.restart.mgmt.usage.server": "Please restart your management server(s) and usage server(s) for your new settings to take effect.",
 "message.restart.network": "All services provided by this network will be interrupted. Please confirm that you want to restart this network.",
+"message.restart.vm.to.update.settings": "Update in fields other than Name and Display Name will require the VM to be restarted",
 "message.restart.vpc": "Please confirm that you want to restart the VPC",
 "message.restart.vpc.remark": "Please confirm that you want to restart the VPC <p><i>Remark: making a non-redundant VPC redundant will force a clean up. The networks will not be available for a couple of minutes</i>.</p>",
 "message.restorevm": "Do you want to restore the VM ?",
diff --git a/ui/src/config/section/compute.js b/ui/src/config/section/compute.js
index 131cd55..8bd694e 100644
--- a/ui/src/config/section/compute.js
+++ b/ui/src/config/section/compute.js
@@ -86,7 +86,6 @@ export default {
           docHelp: 'adminguide/virtual_machines.html#changing-the-vm-name-os-or-group',
           dataView: true,
           popup: true,
-          show: (record) => { return ['Stopped'].includes(record.state) },
           component: () => import('@/views/compute/EditVM.vue')
         },
         {
diff --git a/ui/src/views/compute/EditVM.vue b/ui/src/views/compute/EditVM.vue
index b4b0536..7746d69 100644
--- a/ui/src/views/compute/EditVM.vue
+++ b/ui/src/views/compute/EditVM.vue
@@ -23,6 +23,9 @@
       :form="form"
       v-ctrl-enter="handleSubmit"
       @submit="handleSubmit">
+      <a-alert style="margin-bottom: 5px" type="warning" show-icon>
+        <span slot="message" v-html="$t('message.restart.vm.to.update.settings')" />
+      </a-alert>
       <a-form-item>
         <tooltip-label slot="label" :title="$t('label.name')" :tooltip="apiParams.name.description"/>
         <a-input