Skip to content

Commit

Permalink
feat: Eliminate redundant configuration reads (#5536)
Browse files Browse the repository at this point in the history
When instance id hasn't changed and datasource hasn't changed, don't
forcibly reload the configuration.
  • Loading branch information
holmanb authored Jul 31, 2024
1 parent b5d4f3f commit e6b2e0f
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 6 deletions.
24 changes: 18 additions & 6 deletions cloudinit/stages.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import sys
from collections import namedtuple
from contextlib import suppress
from pathlib import Path
from typing import Dict, Iterable, List, Optional, Set, Tuple, Union

from cloudinit import (
Expand Down Expand Up @@ -459,8 +460,13 @@ def _reflect_cur_instance(self):
# Remove the old symlink and attach a new one so
# that further reads/writes connect into the right location
idir = self._get_ipath()
util.del_file(self.paths.instance_link)
util.sym_link(idir, self.paths.instance_link)
destination = Path(self.paths.instance_link).resolve().absolute()
already_instancified = destination == Path(idir).absolute()
if already_instancified:
LOG.info("Instance link already exists, not recreating it.")
else:
util.del_file(self.paths.instance_link)
util.sym_link(idir, self.paths.instance_link)

# Ensures these dirs exist
dir_list = []
Expand Down Expand Up @@ -499,10 +505,16 @@ def _reflect_cur_instance(self):
)

self._write_to_cache()
# Ensure needed components are regenerated
# after change of instance which may cause
# change of configuration
self._reset()
if already_instancified and previous_ds == ds:
LOG.info(
"Not re-loading configuration, instance "
"id and datasource have not changed."
)
# Ensure needed components are regenerated
# after change of instance which may cause
# change of configuration
else:
self._reset()
return iid

def previous_iid(self):
Expand Down
97 changes: 97 additions & 0 deletions tests/integration_tests/test_instance_id.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
from typing import cast

import pytest
from pycloudlib.lxd.instance import LXDInstance

from cloudinit import subp
from tests.integration_tests.instances import IntegrationInstance
from tests.integration_tests.integration_settings import PLATFORM

_INSTANCE_ID = 0


def setup_meta_data(instance: LXDInstance):
"""Increment the instance id and apply it to the instance."""
global _INSTANCE_ID
_INSTANCE_ID += 1
command = [
"lxc",
"config",
"set",
instance.name,
f"user.meta-data=instance-id: test_{_INSTANCE_ID}",
]
subp.subp(command)


# class TestInstanceID:
@pytest.mark.skipif(
PLATFORM not in ["lxd_container", "lxd_vm"],
reason="Uses lxd-specific behavior.",
)
@pytest.mark.lxd_setup.with_args(setup_meta_data)
@pytest.mark.lxd_use_exec
def test_instance_id_changes(client: IntegrationInstance):
"""Verify instance id change behavior
If the id from the datasource changes, cloud-init should update the
instance id link.
"""
client.execute("cloud-init status --wait")
# check that instance id is the one we set
assert (
"test_1"
== client.execute("cloud-init query instance-id").stdout.rstrip()
)
assert (
"/var/lib/cloud/instances/test_1"
== client.execute(
"readlink -f /var/lib/cloud/instance"
).stdout.rstrip()
)

instance = cast(LXDInstance, client.instance)
setup_meta_data(instance)
client.restart()
client.execute("cloud-init status --wait")
# check that instance id is the one we reset
assert (
"test_2"
== client.execute("cloud-init query instance-id").stdout.rstrip()
)
assert (
"/var/lib/cloud/instances/test_2"
== client.execute(
"readlink -f /var/lib/cloud/instance"
).stdout.rstrip()
)


@pytest.mark.lxd_use_exec
def test_instance_id_no_changes(client: IntegrationInstance):
"""Verify instance id no change behavior
If the id from the datasource does not change, cloud-init should not
update the instance id link.
"""
instance_id = client.execute(
"cloud-init query instance-id"
).stdout.rstrip()
assert (
f"/var/lib/cloud/instances/{instance_id}"
== client.execute(
"readlink -f /var/lib/cloud/instance"
).stdout.rstrip()
)
client.restart()
client.execute("cloud-init status --wait")
assert (
instance_id
== client.execute("cloud-init query instance-id").stdout.rstrip()
)
assert (
f"/var/lib/cloud/instances/{instance_id}"
== client.execute(
"readlink -f /var/lib/cloud/instance"
).stdout.rstrip()
)

0 comments on commit e6b2e0f

Please sign in to comment.