feat(cloud-init): add support for azure-proxy-agent (#9878)
Adds preliminary support for azure-proxy-agent into cloud-init. This is opt-in only with fallbacks if the command isn't available.
This commit is contained in:
Родитель
298bda4a7d
Коммит
ded22fb0a6
|
@ -0,0 +1,114 @@
|
|||
From 402e9331a72d543e779898667488a51ad3e3ec13 Mon Sep 17 00:00:00 2001
|
||||
From: Ksenija Stanojevic <KsenijaS@users.noreply.github.com>
|
||||
Date: Fri, 9 Feb 2024 13:32:19 -0800
|
||||
Subject: [PATCH 1/3] feat(azure): Add ProvisionGuestProxyAgent OVF setting
|
||||
(#4860)
|
||||
|
||||
Add ProvisionGuestProxyAgent Boolean configuration setting into the OvfEnv class.
|
||||
This PR is only logging the value of ProvisionGuestProxyAgent.
|
||||
---
|
||||
cloudinit/sources/DataSourceAzure.py | 6 ++++++
|
||||
cloudinit/sources/helpers/azure.py | 8 ++++++++
|
||||
tests/unittests/sources/test_azure.py | 15 +++++++++++++++
|
||||
3 files changed, 29 insertions(+)
|
||||
|
||||
diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py
|
||||
index 5a82aa34e..dc2b79a3a 100644
|
||||
--- a/cloudinit/sources/DataSourceAzure.py
|
||||
+++ b/cloudinit/sources/DataSourceAzure.py
|
||||
@@ -1784,6 +1784,12 @@ def read_azure_ovf(contents):
|
||||
"PreprovisionedVMType: %s" % ovf_env.preprovisioned_vm_type,
|
||||
logger_func=LOG.info,
|
||||
)
|
||||
+
|
||||
+ cfg["ProvisionGuestProxyAgent"] = ovf_env.provision_guest_proxy_agent
|
||||
+ report_diagnostic_event(
|
||||
+ "ProvisionGuestProxyAgent: %s" % ovf_env.provision_guest_proxy_agent,
|
||||
+ logger_func=LOG.info,
|
||||
+ )
|
||||
return (md, ud, cfg)
|
||||
|
||||
|
||||
diff --git a/cloudinit/sources/helpers/azure.py b/cloudinit/sources/helpers/azure.py
|
||||
index 6e5c1f433..2847a9e53 100644
|
||||
--- a/cloudinit/sources/helpers/azure.py
|
||||
+++ b/cloudinit/sources/helpers/azure.py
|
||||
@@ -1064,6 +1064,7 @@ class OvfEnvXml:
|
||||
public_keys: Optional[List[dict]] = None,
|
||||
preprovisioned_vm: bool = False,
|
||||
preprovisioned_vm_type: Optional[str] = None,
|
||||
+ provision_guest_proxy_agent: bool = False,
|
||||
) -> None:
|
||||
self.username = username
|
||||
self.password = password
|
||||
@@ -1073,6 +1074,7 @@ class OvfEnvXml:
|
||||
self.public_keys: List[dict] = public_keys or []
|
||||
self.preprovisioned_vm = preprovisioned_vm
|
||||
self.preprovisioned_vm_type = preprovisioned_vm_type
|
||||
+ self.provision_guest_proxy_agent = provision_guest_proxy_agent
|
||||
|
||||
def __eq__(self, other) -> bool:
|
||||
return self.__dict__ == other.__dict__
|
||||
@@ -1216,6 +1218,12 @@ class OvfEnvXml:
|
||||
"PreprovisionedVMType",
|
||||
required=False,
|
||||
)
|
||||
+ self.provision_guest_proxy_agent = self._parse_property(
|
||||
+ platform_settings,
|
||||
+ "ProvisionGuestProxyAgent",
|
||||
+ default=False,
|
||||
+ required=False,
|
||||
+ )
|
||||
|
||||
def _parse_ssh_section(self, config_set):
|
||||
self.public_keys = []
|
||||
diff --git a/tests/unittests/sources/test_azure.py b/tests/unittests/sources/test_azure.py
|
||||
index 1ddbd3f39..6afde95fd 100644
|
||||
--- a/tests/unittests/sources/test_azure.py
|
||||
+++ b/tests/unittests/sources/test_azure.py
|
||||
@@ -356,6 +356,7 @@ def construct_ovf_env(
|
||||
disable_ssh_password_auth=None,
|
||||
preprovisioned_vm=None,
|
||||
preprovisioned_vm_type=None,
|
||||
+ provision_guest_proxy_agent=None,
|
||||
):
|
||||
content = [
|
||||
'<?xml version="1.0" encoding="utf-8"?>',
|
||||
@@ -426,6 +427,11 @@ def construct_ovf_env(
|
||||
"<ns1:PreprovisionedVMType>%s</ns1:PreprovisionedVMType>"
|
||||
% preprovisioned_vm_type
|
||||
)
|
||||
+ if provision_guest_proxy_agent is not None:
|
||||
+ content.append(
|
||||
+ "<ns1:ProvisionGuestProxyAgent>%s</ns1:ProvisionGuestProxyAgent>"
|
||||
+ % provision_guest_proxy_agent
|
||||
+ )
|
||||
content += [
|
||||
"</ns1:PlatformSettings>",
|
||||
"</ns1:PlatformSettingsSection>",
|
||||
@@ -1316,6 +1322,7 @@ scbus-1 on xpt0 bus 0
|
||||
expected_cfg = {
|
||||
"PreprovisionedVMType": None,
|
||||
"PreprovisionedVm": False,
|
||||
+ "ProvisionGuestProxyAgent": False,
|
||||
"system_info": {"default_user": {"name": "myuser"}},
|
||||
}
|
||||
expected_metadata = {
|
||||
@@ -2668,6 +2675,14 @@ class TestPreprovisioningReadAzureOvfFlag(CiTestCase):
|
||||
self.assertTrue(cfg["PreprovisionedVm"])
|
||||
self.assertEqual("Savable", cfg["PreprovisionedVMType"])
|
||||
|
||||
+ def test_read_azure_ovf_with_proxy_guest_agent(self):
|
||||
+ """The read_azure_ovf method should set ProvisionGuestProxyAgent
|
||||
+ cfg flag to True."""
|
||||
+ content = construct_ovf_env(provision_guest_proxy_agent=True)
|
||||
+ ret = dsaz.read_azure_ovf(content)
|
||||
+ cfg = ret[2]
|
||||
+ self.assertTrue(cfg["ProvisionGuestProxyAgent"])
|
||||
+
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"ovf_cfg,imds_md,pps_type",
|
||||
--
|
||||
2.34.1
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
From e3ba5800d26065df9ce03ee2ac58ec6f08506423 Mon Sep 17 00:00:00 2001
|
||||
From: Ksenija Stanojevic <KsenijaS@users.noreply.github.com>
|
||||
Date: Fri, 5 Apr 2024 16:52:26 -0700
|
||||
Subject: [PATCH 2/3] feat(azure): parse ProvisionGuestProxyAgent as bool
|
||||
(#5126)
|
||||
|
||||
---
|
||||
cloudinit/sources/helpers/azure.py | 1 +
|
||||
tests/unittests/sources/test_azure.py | 12 ++++++++++--
|
||||
2 files changed, 11 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/cloudinit/sources/helpers/azure.py b/cloudinit/sources/helpers/azure.py
|
||||
index 2847a9e53..165f47429 100644
|
||||
--- a/cloudinit/sources/helpers/azure.py
|
||||
+++ b/cloudinit/sources/helpers/azure.py
|
||||
@@ -1221,6 +1221,7 @@ class OvfEnvXml:
|
||||
self.provision_guest_proxy_agent = self._parse_property(
|
||||
platform_settings,
|
||||
"ProvisionGuestProxyAgent",
|
||||
+ parse_bool=True,
|
||||
default=False,
|
||||
required=False,
|
||||
)
|
||||
diff --git a/tests/unittests/sources/test_azure.py b/tests/unittests/sources/test_azure.py
|
||||
index 6afde95fd..255991ec3 100644
|
||||
--- a/tests/unittests/sources/test_azure.py
|
||||
+++ b/tests/unittests/sources/test_azure.py
|
||||
@@ -2675,13 +2675,21 @@ class TestPreprovisioningReadAzureOvfFlag(CiTestCase):
|
||||
self.assertTrue(cfg["PreprovisionedVm"])
|
||||
self.assertEqual("Savable", cfg["PreprovisionedVMType"])
|
||||
|
||||
- def test_read_azure_ovf_with_proxy_guest_agent(self):
|
||||
+ def test_read_azure_ovf_with_proxy_guest_agent_true(self):
|
||||
"""The read_azure_ovf method should set ProvisionGuestProxyAgent
|
||||
cfg flag to True."""
|
||||
content = construct_ovf_env(provision_guest_proxy_agent=True)
|
||||
ret = dsaz.read_azure_ovf(content)
|
||||
cfg = ret[2]
|
||||
- self.assertTrue(cfg["ProvisionGuestProxyAgent"])
|
||||
+ assert cfg["ProvisionGuestProxyAgent"] is True
|
||||
+
|
||||
+ def test_read_azure_ovf_with_proxy_guest_agent_false(self):
|
||||
+ """The read_azure_ovf method should set ProvisionGuestProxyAgent
|
||||
+ cfg flag to False."""
|
||||
+ content = construct_ovf_env(provision_guest_proxy_agent=False)
|
||||
+ ret = dsaz.read_azure_ovf(content)
|
||||
+ cfg = ret[2]
|
||||
+ assert cfg["ProvisionGuestProxyAgent"] is False
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
--
|
||||
2.34.1
|
||||
|
|
@ -0,0 +1,413 @@
|
|||
From 8932242a65bae5504ba45134091767f215a441fa Mon Sep 17 00:00:00 2001
|
||||
From: Ksenija Stanojevic <ksenija.stanojevic@gmail.com>
|
||||
Date: Mon, 15 Jul 2024 18:48:19 -0700
|
||||
Subject: [PATCH 3/3] feat(azure): add support for azure-proxy-agent
|
||||
|
||||
---
|
||||
cloudinit/sources/DataSourceAzure.py | 40 ++++
|
||||
cloudinit/sources/azure/errors.py | 19 +-
|
||||
tests/unittests/sources/test_azure.py | 254 ++++++++++++++++++++++++++
|
||||
3 files changed, 312 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py
|
||||
index dc2b79a3a..c2f74e173 100644
|
||||
--- a/cloudinit/sources/DataSourceAzure.py
|
||||
+++ b/cloudinit/sources/DataSourceAzure.py
|
||||
@@ -483,6 +483,41 @@ class DataSourceAzure(sources.DataSource):
|
||||
or self._ephemeral_dhcp_ctx.lease is None
|
||||
)
|
||||
|
||||
+ def _check_azure_proxy_agent_status(self) -> None:
|
||||
+ """Check if azure-proxy-agent is ready for communication with WS/IMDS.
|
||||
+ If ProvisionGuestProxyAgent is true, query azure-proxy-agent status,
|
||||
+ waiting up to 120 seconds for the proxy to negotiate with Wireserver
|
||||
+ and configure an eBPF proxy. Once azure-proxy-agent is ready,
|
||||
+ it will exit with code 0 and cloud-init can then expect to be able to
|
||||
+ communicate with these services.
|
||||
+ Fail deployment if azure-proxy-agent is not found or otherwise returns
|
||||
+ an error.
|
||||
+ For more information, check out:
|
||||
+ https://github.com/azure/guestproxyagent
|
||||
+ """
|
||||
+ try:
|
||||
+ cmd = [
|
||||
+ "azure-proxy-agent",
|
||||
+ "--status",
|
||||
+ "--wait",
|
||||
+ "120",
|
||||
+ ]
|
||||
+ out, err = subp.subp(cmd)
|
||||
+ report_diagnostic_event(
|
||||
+ "Running azure-proxy-agent %s resulted"
|
||||
+ "in stderr output: %s with stdout: %s" % (cmd, err, out),
|
||||
+ logger_func=LOG.debug,
|
||||
+ )
|
||||
+ except subp.ProcessExecutionError as error:
|
||||
+ if isinstance(error.reason, FileNotFoundError):
|
||||
+ report_error = errors.ReportableErrorProxyAgentNotFound()
|
||||
+ self._report_failure(report_error)
|
||||
+ else:
|
||||
+ reportable_error = (
|
||||
+ errors.ReportableErrorProxyAgentStatusFailure(error)
|
||||
+ )
|
||||
+ self._report_failure(reportable_error)
|
||||
+
|
||||
@azure_ds_telemetry_reporter
|
||||
def crawl_metadata(self):
|
||||
"""Walk all instance metadata sources returning a dict on success.
|
||||
@@ -566,6 +601,11 @@ class DataSourceAzure(sources.DataSource):
|
||||
|
||||
imds_md = {}
|
||||
if self._is_ephemeral_networking_up():
|
||||
+ # check if azure-proxy-agent is enabled in the ovf-env.xml file.
|
||||
+ # azure-proxy-agent feature is opt-in and disabled by default.
|
||||
+ if cfg.get("ProvisionGuestProxyAgent"):
|
||||
+ self._check_azure_proxy_agent_status()
|
||||
+
|
||||
imds_md = self.get_metadata_from_imds(report_failure=True)
|
||||
|
||||
if not imds_md and ovf_source is None:
|
||||
diff --git a/cloudinit/sources/azure/errors.py b/cloudinit/sources/azure/errors.py
|
||||
index 966725b00..b331cd686 100644
|
||||
--- a/cloudinit/sources/azure/errors.py
|
||||
+++ b/cloudinit/sources/azure/errors.py
|
||||
@@ -12,7 +12,7 @@ from typing import Any, Dict, List, Optional
|
||||
|
||||
import requests
|
||||
|
||||
-from cloudinit import version
|
||||
+from cloudinit import subp, version
|
||||
from cloudinit.sources.azure import identity
|
||||
from cloudinit.url_helper import UrlError
|
||||
|
||||
@@ -151,3 +151,20 @@ class ReportableErrorUnhandledException(ReportableError):
|
||||
|
||||
self.supporting_data["exception"] = repr(exception)
|
||||
self.supporting_data["traceback_base64"] = trace_base64
|
||||
+
|
||||
+
|
||||
+class ReportableErrorProxyAgentNotFound(ReportableError):
|
||||
+ def __init__(self) -> None:
|
||||
+ super().__init__(
|
||||
+ "Unable to activate Azure Guest Proxy Agent."
|
||||
+ "azure-proxy-agent not found"
|
||||
+ )
|
||||
+
|
||||
+
|
||||
+class ReportableErrorProxyAgentStatusFailure(ReportableError):
|
||||
+ def __init__(self, exception: subp.ProcessExecutionError) -> None:
|
||||
+ super().__init__("azure-proxy-agent status failure")
|
||||
+
|
||||
+ self.supporting_data["exit_code"] = exception.exit_code
|
||||
+ self.supporting_data["stdout"] = exception.stdout
|
||||
+ self.supporting_data["stderr"] = exception.stderr
|
||||
diff --git a/tests/unittests/sources/test_azure.py b/tests/unittests/sources/test_azure.py
|
||||
index 255991ec3..9b6672e1e 100644
|
||||
--- a/tests/unittests/sources/test_azure.py
|
||||
+++ b/tests/unittests/sources/test_azure.py
|
||||
@@ -1,6 +1,7 @@
|
||||
# This file is part of cloud-init. See LICENSE file for license information.
|
||||
|
||||
import copy
|
||||
+import datetime
|
||||
import json
|
||||
import os
|
||||
import stat
|
||||
@@ -48,6 +49,16 @@ def mock_wrapping_setup_ephemeral_networking(azure_ds):
|
||||
yield m
|
||||
|
||||
|
||||
+@pytest.fixture
|
||||
+def mock_wrapping_report_failure(azure_ds):
|
||||
+ with mock.patch.object(
|
||||
+ azure_ds,
|
||||
+ "_report_failure",
|
||||
+ wraps=azure_ds._report_failure,
|
||||
+ ) as m:
|
||||
+ yield m
|
||||
+
|
||||
+
|
||||
@pytest.fixture
|
||||
def mock_azure_helper_readurl():
|
||||
with mock.patch(
|
||||
@@ -253,6 +264,14 @@ def mock_subp_subp():
|
||||
yield m
|
||||
|
||||
|
||||
+@pytest.fixture
|
||||
+def mock_timestamp():
|
||||
+ timestamp = datetime.datetime.utcnow()
|
||||
+ with mock.patch.object(errors, "datetime", autospec=True) as m:
|
||||
+ m.utcnow.return_value = timestamp
|
||||
+ yield timestamp
|
||||
+
|
||||
+
|
||||
@pytest.fixture
|
||||
def mock_util_ensure_dir():
|
||||
with mock.patch(
|
||||
@@ -3672,6 +3691,91 @@ class TestProvisioning:
|
||||
}
|
||||
|
||||
def test_no_pps(self):
|
||||
+ ovf = construct_ovf_env(provision_guest_proxy_agent=False)
|
||||
+ md, ud, cfg = dsaz.read_azure_ovf(ovf)
|
||||
+ self.mock_util_mount_cb.return_value = (md, ud, cfg, {})
|
||||
+ self.mock_readurl.side_effect = [
|
||||
+ mock.MagicMock(contents=json.dumps(self.imds_md).encode()),
|
||||
+ ]
|
||||
+ self.mock_azure_get_metadata_from_fabric.return_value = []
|
||||
+
|
||||
+ self.azure_ds._check_and_get_data()
|
||||
+
|
||||
+ assert self.mock_subp_subp.mock_calls == []
|
||||
+
|
||||
+ assert self.mock_readurl.mock_calls == [
|
||||
+ mock.call(
|
||||
+ "http://169.254.169.254/metadata/instance?"
|
||||
+ "api-version=2021-08-01&extended=true",
|
||||
+ timeout=30,
|
||||
+ headers_cb=imds.headers_cb,
|
||||
+ exception_cb=mock.ANY,
|
||||
+ infinite=True,
|
||||
+ log_req_resp=True,
|
||||
+ ),
|
||||
+ ]
|
||||
+
|
||||
+ # Verify DHCP is setup once.
|
||||
+ assert self.mock_wrapping_setup_ephemeral_networking.mock_calls == [
|
||||
+ mock.call(timeout_minutes=20)
|
||||
+ ]
|
||||
+ assert self.mock_net_dhcp_maybe_perform_dhcp_discovery.mock_calls == [
|
||||
+ mock.call(
|
||||
+ self.azure_ds.distro,
|
||||
+ None,
|
||||
+ dsaz.dhcp_log_cb,
|
||||
+ )
|
||||
+ ]
|
||||
+ assert self.azure_ds._wireserver_endpoint == "10.11.12.13"
|
||||
+ assert self.azure_ds._is_ephemeral_networking_up() is False
|
||||
+
|
||||
+ # Verify DMI usage.
|
||||
+ assert self.mock_dmi_read_dmi_data.mock_calls == [
|
||||
+ mock.call("chassis-asset-tag"),
|
||||
+ mock.call("system-uuid"),
|
||||
+ ]
|
||||
+ assert (
|
||||
+ self.azure_ds.metadata["instance-id"]
|
||||
+ == "50109936-ef07-47fe-ac82-890c853f60d5"
|
||||
+ )
|
||||
+
|
||||
+ # Verify IMDS metadata.
|
||||
+ assert self.azure_ds.metadata["imds"] == self.imds_md
|
||||
+
|
||||
+ # Verify reporting ready once.
|
||||
+ assert self.mock_azure_get_metadata_from_fabric.mock_calls == [
|
||||
+ mock.call(
|
||||
+ endpoint="10.11.12.13",
|
||||
+ distro=self.azure_ds.distro,
|
||||
+ iso_dev="/dev/sr0",
|
||||
+ pubkey_info=None,
|
||||
+ )
|
||||
+ ]
|
||||
+
|
||||
+ # Verify netlink.
|
||||
+ assert self.mock_netlink.mock_calls == []
|
||||
+
|
||||
+ # Verify no reported_ready marker written.
|
||||
+ assert self.wrapped_util_write_file.mock_calls == []
|
||||
+ assert self.patched_reported_ready_marker_path.exists() is False
|
||||
+
|
||||
+ # Verify reports via KVP.
|
||||
+ assert len(self.mock_kvp_report_failure_to_host.mock_calls) == 0
|
||||
+ assert len(self.mock_azure_report_failure_to_fabric.mock_calls) == 0
|
||||
+ assert len(self.mock_kvp_report_success_to_host.mock_calls) == 1
|
||||
+
|
||||
+ # Verify dmesg reported via KVP.
|
||||
+ assert len(self.mock_report_dmesg_to_kvp.mock_calls) == 1
|
||||
+
|
||||
+ def test_no_pps_gpa(self):
|
||||
+ """test full provisioning scope when azure-proxy-agent
|
||||
+ is enabled and running."""
|
||||
+ self.mock_subp_subp.side_effect = [
|
||||
+ subp.SubpResult("Guest Proxy Agent running", ""),
|
||||
+ ]
|
||||
+ ovf = construct_ovf_env(provision_guest_proxy_agent=True)
|
||||
+ md, ud, cfg = dsaz.read_azure_ovf(ovf)
|
||||
+ self.mock_util_mount_cb.return_value = (md, ud, cfg, {})
|
||||
self.mock_readurl.side_effect = [
|
||||
mock.MagicMock(contents=json.dumps(self.imds_md).encode()),
|
||||
]
|
||||
@@ -3679,6 +3783,11 @@ class TestProvisioning:
|
||||
|
||||
self.azure_ds._check_and_get_data()
|
||||
|
||||
+ assert self.mock_subp_subp.mock_calls == [
|
||||
+ mock.call(
|
||||
+ ["azure-proxy-agent", "--status", "--wait", "120"],
|
||||
+ ),
|
||||
+ ]
|
||||
assert self.mock_readurl.mock_calls == [
|
||||
mock.call(
|
||||
"http://169.254.169.254/metadata/instance?"
|
||||
@@ -3736,6 +3845,93 @@ class TestProvisioning:
|
||||
|
||||
# Verify reports via KVP.
|
||||
assert len(self.mock_kvp_report_failure_to_host.mock_calls) == 0
|
||||
+ assert len(self.mock_azure_report_failure_to_fabric.mock_calls) == 0
|
||||
+ assert len(self.mock_kvp_report_success_to_host.mock_calls) == 1
|
||||
+
|
||||
+ def test_no_pps_gpa_fail(self):
|
||||
+ """test full provisioning scope when azure-proxy-agent is enabled and
|
||||
+ throwing an exception during provisioning."""
|
||||
+ self.mock_subp_subp.side_effect = [
|
||||
+ subp.ProcessExecutionError(
|
||||
+ cmd=["failed", "azure-proxy-agent"],
|
||||
+ stdout="test_stdout",
|
||||
+ stderr="test_stderr",
|
||||
+ exit_code=4,
|
||||
+ ),
|
||||
+ ]
|
||||
+ ovf = construct_ovf_env(provision_guest_proxy_agent=True)
|
||||
+ md, ud, cfg = dsaz.read_azure_ovf(ovf)
|
||||
+ self.mock_util_mount_cb.return_value = (md, ud, cfg, {})
|
||||
+ self.mock_readurl.side_effect = [
|
||||
+ mock.MagicMock(contents=json.dumps(self.imds_md).encode()),
|
||||
+ ]
|
||||
+ self.mock_azure_get_metadata_from_fabric.return_value = []
|
||||
+
|
||||
+ self.azure_ds._check_and_get_data()
|
||||
+
|
||||
+ assert self.mock_subp_subp.mock_calls == [
|
||||
+ mock.call(
|
||||
+ ["azure-proxy-agent", "--status", "--wait", "120"],
|
||||
+ ),
|
||||
+ ]
|
||||
+ assert self.mock_readurl.mock_calls == [
|
||||
+ mock.call(
|
||||
+ "http://169.254.169.254/metadata/instance?"
|
||||
+ "api-version=2021-08-01&extended=true",
|
||||
+ timeout=30,
|
||||
+ headers={"Metadata": "true"},
|
||||
+ exception_cb=mock.ANY,
|
||||
+ infinite=True,
|
||||
+ log_req_resp=True,
|
||||
+ ),
|
||||
+ ]
|
||||
+
|
||||
+ # Verify DHCP is setup once.
|
||||
+ assert self.mock_wrapping_setup_ephemeral_networking.mock_calls == [
|
||||
+ mock.call(timeout_minutes=20)
|
||||
+ ]
|
||||
+ assert self.mock_net_dhcp_maybe_perform_dhcp_discovery.mock_calls == [
|
||||
+ mock.call(
|
||||
+ self.azure_ds.distro,
|
||||
+ None,
|
||||
+ dsaz.dhcp_log_cb,
|
||||
+ )
|
||||
+ ]
|
||||
+ assert self.azure_ds._wireserver_endpoint == "10.11.12.13"
|
||||
+ assert self.azure_ds._is_ephemeral_networking_up() is False
|
||||
+
|
||||
+ # Verify DMI usage.
|
||||
+ assert self.mock_dmi_read_dmi_data.mock_calls == [
|
||||
+ mock.call("chassis-asset-tag"),
|
||||
+ mock.call("system-uuid"),
|
||||
+ mock.call("system-uuid"),
|
||||
+ ]
|
||||
+ assert (
|
||||
+ self.azure_ds.metadata["instance-id"]
|
||||
+ == "50109936-ef07-47fe-ac82-890c853f60d5"
|
||||
+ )
|
||||
+
|
||||
+ # Verify IMDS metadata.
|
||||
+ assert self.azure_ds.metadata["imds"] == self.imds_md
|
||||
+
|
||||
+ ### BACKPORT NOTE: 23.3 _will_ report ready later after failure.
|
||||
+ ### In newer versions there will be no call to report ready after failure.
|
||||
+ assert self.mock_azure_get_metadata_from_fabric.mock_calls == [
|
||||
+ mock.call(
|
||||
+ endpoint="10.11.12.13", iso_dev="/dev/sr0", pubkey_info=None
|
||||
+ )
|
||||
+ ]
|
||||
+
|
||||
+ # Verify netlink.
|
||||
+ assert self.mock_netlink.mock_calls == []
|
||||
+
|
||||
+ # Verify no reported_ready marker written.
|
||||
+ assert self.wrapped_util_write_file.mock_calls == []
|
||||
+ assert self.patched_reported_ready_marker_path.exists() is False
|
||||
+
|
||||
+ # Verify reports via KVP.
|
||||
+ assert len(self.mock_kvp_report_failure_to_host.mock_calls) == 1
|
||||
+ assert len(self.mock_azure_report_failure_to_fabric.mock_calls) == 1
|
||||
assert len(self.mock_kvp_report_success_to_host.mock_calls) == 1
|
||||
|
||||
def test_running_pps(self):
|
||||
@@ -4315,6 +4511,64 @@ class TestProvisioning:
|
||||
assert len(self.mock_kvp_report_success_to_host.mock_calls) == 1
|
||||
|
||||
|
||||
+class TestCheckAzureProxyAgent:
|
||||
+ @pytest.fixture(autouse=True)
|
||||
+ def proxy_setup(
|
||||
+ self,
|
||||
+ azure_ds,
|
||||
+ mock_subp_subp,
|
||||
+ caplog,
|
||||
+ mock_wrapping_report_failure,
|
||||
+ mock_timestamp,
|
||||
+ ):
|
||||
+ self.azure_ds = azure_ds
|
||||
+ self.mock_subp_subp = mock_subp_subp
|
||||
+ self.caplog = caplog
|
||||
+ self.mock_wrapping_report_failure = mock_wrapping_report_failure
|
||||
+ self.mock_timestamp = mock_timestamp
|
||||
+
|
||||
+ def test_check_azure_proxy_agent_status(self):
|
||||
+ self.mock_subp_subp.side_effect = [
|
||||
+ subp.SubpResult("Guest Proxy Agent running", ""),
|
||||
+ ]
|
||||
+ self.azure_ds._check_azure_proxy_agent_status()
|
||||
+ assert "Running azure-proxy-agent" in self.caplog.text
|
||||
+ assert self.mock_wrapping_report_failure.mock_calls == []
|
||||
+
|
||||
+ def test_check_azure_proxy_agent_status_notfound(self):
|
||||
+ exception = subp.ProcessExecutionError(reason=FileNotFoundError())
|
||||
+ self.mock_subp_subp.side_effect = [
|
||||
+ exception,
|
||||
+ ]
|
||||
+ self.azure_ds._check_azure_proxy_agent_status()
|
||||
+ assert "azure-proxy-agent not found" in self.caplog.text
|
||||
+ assert self.mock_wrapping_report_failure.mock_calls == [
|
||||
+ mock.call(
|
||||
+ errors.ReportableErrorProxyAgentNotFound(),
|
||||
+ ),
|
||||
+ ]
|
||||
+
|
||||
+ def test_check_azure_proxy_agent_status_failure(self):
|
||||
+ exception = subp.ProcessExecutionError(
|
||||
+ cmd=["failed", "azure-proxy-agent"],
|
||||
+ stdout="test_stdout",
|
||||
+ stderr="test_stderr",
|
||||
+ exit_code=4,
|
||||
+ )
|
||||
+ self.mock_subp_subp.side_effect = [
|
||||
+ exception,
|
||||
+ ]
|
||||
+ self.azure_ds._check_azure_proxy_agent_status()
|
||||
+ assert "azure-proxy-agent status failure" in self.caplog.text
|
||||
+ assert self.mock_wrapping_report_failure.mock_calls == [
|
||||
+ mock.call(
|
||||
+ errors.ReportableErrorProxyAgentStatusFailure(
|
||||
+ exception=exception
|
||||
+ ),
|
||||
+ ),
|
||||
+ ]
|
||||
+
|
||||
+
|
||||
class TestGetMetadataFromImds:
|
||||
@pytest.mark.parametrize("report_failure", [False, True])
|
||||
@pytest.mark.parametrize(
|
||||
--
|
||||
2.34.1
|
||||
|
|
@ -5,7 +5,7 @@ Summary: Cloud instance init scripts
|
|||
Name: cloud-init
|
||||
Epoch: 1
|
||||
Version: %{package_version}
|
||||
Release: 3%{?dist}
|
||||
Release: 4%{?dist}
|
||||
License: GPLv3
|
||||
Vendor: Microsoft Corporation
|
||||
Distribution: Mariner
|
||||
|
@ -16,6 +16,9 @@ Source1: 10-azure-kvp.cfg
|
|||
Patch0: overrideDatasourceDetection.patch
|
||||
Patch1: exec_cmd_error_handling.patch
|
||||
Patch2: Add-Network-Interface-Renaming-Support-for-CAPM3-Met.patch
|
||||
Patch3: 0001-feat-azure-Add-ProvisionGuestProxyAgent-OVF-setting-.patch
|
||||
Patch4: 0002-feat-azure-parse-ProvisionGuestProxyAgent-as-bool-51.patch
|
||||
Patch5: 0003-feat-azure-add-support-for-azure-proxy-agent.patch
|
||||
%define cl_services cloud-config.service cloud-config.target cloud-final.service cloud-init.service cloud-init.target cloud-init-local.service
|
||||
BuildRequires: automake
|
||||
BuildRequires: dbus
|
||||
|
@ -151,6 +154,9 @@ make check %{?_smp_mflags}
|
|||
%config(noreplace) %{_sysconfdir}/cloud/cloud.cfg.d/10-azure-kvp.cfg
|
||||
|
||||
%changelog
|
||||
* Mon July 15 2024 Ksenija Stanojevic <ksstanoj@microsoft.com> - 23.3.3-4
|
||||
- Add patches to support azure-proxy-agent.
|
||||
|
||||
* Wed May 8 2024 Sharath Srikanth Chellappa <sharathsr@microsoft.com> - 1:23.3-3
|
||||
- Add patch to add network interface renaming support for CAPM3 Met.
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче