|
70 | 70 |
|
71 | 71 | _multiprocess_shared_ = True |
72 | 72 |
|
73 | | -# Directory on KVM agents where network-namespace scripts are installed |
74 | | -EXTENSIONS_DIR = '/etc/cloudstack/extensions/network-namespace' |
| 73 | +# Base directory on KVM agents where wrapper scripts are installed. |
| 74 | +# The actual per-extension subdirectory is derived at runtime from the |
| 75 | +# extension name: /etc/cloudstack/extensions/<ext-name>/ |
| 76 | +EXTENSIONS_BASE_DIR = '/etc/cloudstack/extensions' |
75 | 77 | SCRIPT_FILENAME = 'network-namespace-wrapper.sh' |
76 | 78 | ENTRY_POINT_FILENAME = 'network-namespace.sh' |
77 | 79 |
|
@@ -306,9 +308,10 @@ class KvmHostDeployer: |
306 | 308 | """Copies the KVM wrapper script to all KVM hosts via SSH. |
307 | 309 |
|
308 | 310 | *dest_path* is the absolute path on each KVM host where the wrapper |
309 | | - script is installed. It must be identical to the management-server |
310 | | - extension path so that both the entry-point and the wrapper share the |
311 | | - same directory and filename on their respective machines. |
| 311 | + script is installed. This path differs from the management-server |
| 312 | + entry-point path: |
| 313 | + management server: /usr/share/cloudstack-management/extensions/<name>/<name>.sh |
| 314 | + KVM host (wrapper): /etc/cloudstack/extensions/<name>/<name>-wrapper.sh |
312 | 315 | """ |
313 | 316 |
|
314 | 317 | def __init__(self, config_hosts=None, logger=None, dest_path=None): |
@@ -459,6 +462,7 @@ def setUp(self): |
459 | 462 | self.extension_path = None |
460 | 463 | self.mgmt_deployer = None |
461 | 464 | self._mgmt_script_path = None |
| 465 | + self._all_mgmt_deployers = [] |
462 | 466 | self.kvm_deployer = None |
463 | 467 | self._ssh_private_key_file = None |
464 | 468 |
|
@@ -520,40 +524,70 @@ def _delete_provider(self, provider_id): |
520 | 524 | # ------------------------------------------------------------------ |
521 | 525 |
|
522 | 526 | def _deploy_scripts(self): |
523 | | - """Deploy scripts to management server and all KVM hosts. |
524 | | -
|
525 | | - Both the entry-point (network-namespace.sh) and the KVM wrapper |
526 | | - (network-namespace-wrapper.sh) are deployed to the **same path**: |
527 | | - ``self.extension_path``. The management server receives the |
528 | | - entry-point script; each KVM host receives the wrapper script — both |
529 | | - under the same directory and filename so that the entry-point can call |
530 | | - the wrapper via its own ``$0`` path without any hard-coded name. |
| 527 | + """Deploy scripts to all management servers and all KVM hosts. |
| 528 | +
|
| 529 | + The entry-point (network-namespace.sh) is deployed to every management |
| 530 | + server at ``self.extension_path`` (the path CloudStack assigned to the |
| 531 | + extension, e.g. |
| 532 | + ``/usr/share/cloudstack-management/extensions/<name>/<name>.sh``). |
| 533 | +
|
| 534 | + The KVM wrapper (network-namespace-wrapper.sh) is deployed to each KVM |
| 535 | + host at a *different* path derived from the extension name: |
| 536 | + ``/etc/cloudstack/extensions/<name>/<name>-wrapper.sh`` |
| 537 | +
|
| 538 | + The entry-point script uses the same derivation at runtime (see |
| 539 | + DEFAULT_SCRIPT_PATH in network-namespace.sh) so that it always calls |
| 540 | + the correct wrapper on the remote KVM host. |
531 | 541 | """ |
532 | 542 | wrapper_src, entry_point_src = _ensure_scripts_downloaded() |
533 | 543 |
|
534 | | - self.mgmt_deployer = MgmtServerDeployer(self.mgtSvrDetails, |
535 | | - logger=self.logger) |
536 | 544 | self._mgmt_script_path = (self.extension_path or "").strip().rstrip('/') |
537 | | - self.mgmt_deployer.copy_file(entry_point_src, self._mgmt_script_path) |
538 | | - self.logger.info("Entry-point script deployed to mgmt at %s", |
539 | | - self._mgmt_script_path) |
540 | 545 |
|
541 | | - # Deploy the wrapper to KVM hosts at the SAME path as the management |
542 | | - # server entry-point so that both scripts share the same directory and |
543 | | - # filename on their respective hosts. |
| 546 | + # Deploy entry-point to ALL management servers |
| 547 | + all_mgt_svrs = self.config.__dict__.get("mgtSvr", []) |
| 548 | + self._all_mgmt_deployers = [] |
| 549 | + for mgt in all_mgt_svrs: |
| 550 | + mgt_details = mgt.__dict__ if hasattr(mgt, '__dict__') else mgt |
| 551 | + deployer = MgmtServerDeployer(mgt_details, logger=self.logger) |
| 552 | + deployer.copy_file(entry_point_src, self._mgmt_script_path) |
| 553 | + self.logger.info("Entry-point deployed to mgmt %s at %s", |
| 554 | + mgt_details.get("mgtSvrIp", "?"), |
| 555 | + self._mgmt_script_path) |
| 556 | + self._all_mgmt_deployers.append(deployer) |
| 557 | + |
| 558 | + # Keep mgmt_deployer pointing at the primary server for backward-compat |
| 559 | + self.mgmt_deployer = (self._all_mgmt_deployers[0] |
| 560 | + if self._all_mgmt_deployers |
| 561 | + else MgmtServerDeployer(self.mgtSvrDetails, |
| 562 | + logger=self.logger)) |
| 563 | + |
| 564 | + # Derive the wrapper destination path on KVM hosts from the extension path: |
| 565 | + # mgmt: .../extensions/<name>/<name>.sh |
| 566 | + # kvm: /etc/cloudstack/extensions/<name>/<name>-wrapper.sh |
| 567 | + ext_dir_name = os.path.basename(os.path.dirname(self._mgmt_script_path)) |
| 568 | + script_basename = os.path.splitext( |
| 569 | + os.path.basename(self._mgmt_script_path))[0] |
| 570 | + kvm_wrapper_path = "/etc/cloudstack/extensions/%s/%s-wrapper.sh" % ( |
| 571 | + ext_dir_name, script_basename) |
| 572 | + |
544 | 573 | self.kvm_deployer = KvmHostDeployer( |
545 | 574 | config_hosts=self.kvm_host_configs, |
546 | 575 | logger=self.logger, |
547 | | - dest_path=self._mgmt_script_path, |
| 576 | + dest_path=kvm_wrapper_path, |
548 | 577 | ) |
549 | 578 | deployed = self.kvm_deployer.deploy() |
550 | 579 | self.logger.info( |
551 | 580 | "KVM wrapper deployed to %d host(s) at %s: %s", |
552 | | - len(deployed), self._mgmt_script_path, deployed) |
| 581 | + len(deployed), kvm_wrapper_path, deployed) |
553 | 582 |
|
554 | 583 | def _cleanup_mgmt_script(self): |
555 | | - if self.mgmt_deployer and self._mgmt_script_path: |
556 | | - self.mgmt_deployer.remove_file(self._mgmt_script_path) |
| 584 | + if self._mgmt_script_path: |
| 585 | + all_deployers = getattr(self, '_all_mgmt_deployers', None) or [] |
| 586 | + if all_deployers: |
| 587 | + for deployer in all_deployers: |
| 588 | + deployer.remove_file(self._mgmt_script_path) |
| 589 | + elif self.mgmt_deployer: |
| 590 | + self.mgmt_deployer.remove_file(self._mgmt_script_path) |
557 | 591 | self._mgmt_script_path = None |
558 | 592 |
|
559 | 593 | # ------------------------------------------------------------------ |
|
0 commit comments