summaryrefslogtreecommitdiff
path: root/cloudinit/cmd
diff options
context:
space:
mode:
authorChad Smith <chad.smith@canonical.com>2022-01-13 10:12:23 -0700
committerGitHub <noreply@github.com>2022-01-13 11:12:23 -0600
commit0de7acb194dc15650eee1d5332efed82ef162f84 (patch)
treee223562b3031a82894ceda71d6361aad9f570732 /cloudinit/cmd
parente3f3485d875f021915654bf2b64678e151a8d6f6 (diff)
downloadcloud-init-git-0de7acb194dc15650eee1d5332efed82ef162f84.tar.gz
cli: cloud-id report not-run or disabled state as cloud-id (#1162)
This fix has two elements: - cloud-init status will not correctly report 'not-run' prior to systemd generator running. Only report "disabled" when generator has run and /run/cloud-init/disabled exists. - Expose not-run and disabled state in cloud-id responses - Add unique error codes from cloud-id for error, disabled and not-run. The new cloud-id exit codes: 0: success 1: error 2: cloud-init is in disabled state 3: cloud-init generator has not run yet
Diffstat (limited to 'cloudinit/cmd')
-rwxr-xr-xcloudinit/cmd/cloud_id.py11
-rw-r--r--cloudinit/cmd/status.py58
2 files changed, 44 insertions, 25 deletions
diff --git a/cloudinit/cmd/cloud_id.py b/cloudinit/cmd/cloud_id.py
index b92b03a8..b71c19de 100755
--- a/cloudinit/cmd/cloud_id.py
+++ b/cloudinit/cmd/cloud_id.py
@@ -6,6 +6,7 @@ import argparse
import json
import sys
+from cloudinit.cmd.status import UXAppStatus, get_status_details
from cloudinit.sources import (
INSTANCE_JSON_FILE,
METADATA_UNKNOWN,
@@ -62,8 +63,16 @@ def handle_args(name, args):
Print the canonical cloud-id on which the instance is running.
- @return: 0 on success, 1 otherwise.
+ @return: 0 on success, 1 on error, 2 on disabled, 3 on cloud-init not-run.
"""
+ status, _status_details, _time = get_status_details()
+ if status == UXAppStatus.DISABLED:
+ sys.stdout.write("{0}\n".format(status.value))
+ return 2
+ elif status == UXAppStatus.NOT_RUN:
+ sys.stdout.write("{0}\n".format(status.value))
+ return 3
+
try:
instance_data = json.load(open(args.instance_data))
except IOError:
diff --git a/cloudinit/cmd/status.py b/cloudinit/cmd/status.py
index cff16c34..597e5bfb 100644
--- a/cloudinit/cmd/status.py
+++ b/cloudinit/cmd/status.py
@@ -5,6 +5,7 @@
"""Define 'status' utility and handler as part of cloud-init commandline."""
import argparse
+import enum
import os
import sys
from time import gmtime, sleep, strftime
@@ -15,12 +16,17 @@ from cloudinit.util import get_cmdline, load_file, load_json
CLOUDINIT_DISABLED_FILE = "/etc/cloud/cloud-init.disabled"
+
# customer visible status messages
-STATUS_ENABLED_NOT_RUN = "not run"
-STATUS_RUNNING = "running"
-STATUS_DONE = "done"
-STATUS_ERROR = "error"
-STATUS_DISABLED = "disabled"
+@enum.unique
+class UXAppStatus(enum.Enum):
+ """Enum representing user-visible cloud-init application status."""
+
+ NOT_RUN = "not-run"
+ RUNNING = "running"
+ DONE = "done"
+ ERROR = "error"
+ DISABLED = "disabled"
def get_parser(parser=None):
@@ -61,23 +67,20 @@ def handle_status_args(name, args):
# Read configured paths
init = Init(ds_deps=[])
init.read_cfg()
-
- status, status_detail, time = _get_status_details(init.paths)
+ status, status_detail, time = get_status_details(init.paths)
if args.wait:
- while status in (STATUS_ENABLED_NOT_RUN, STATUS_RUNNING):
+ while status in (UXAppStatus.NOT_RUN, UXAppStatus.RUNNING):
sys.stdout.write(".")
sys.stdout.flush()
- status, status_detail, time = _get_status_details(init.paths)
+ status, status_detail, time = get_status_details(init.paths)
sleep(0.25)
sys.stdout.write("\n")
+ print("status: {0}".format(status.value))
if args.long:
- print("status: {0}".format(status))
if time:
print("time: {0}".format(time))
print("detail:\n{0}".format(status_detail))
- else:
- print("status: {0}".format(status))
- return 1 if status == STATUS_ERROR else 0
+ return 1 if status == UXAppStatus.ERROR else 0
def _is_cloudinit_disabled(disable_file, paths):
@@ -100,22 +103,29 @@ def _is_cloudinit_disabled(disable_file, paths):
elif "cloud-init=disabled" in cmdline_parts:
is_disabled = True
reason = "Cloud-init disabled by kernel parameter cloud-init=disabled"
- elif not os.path.exists(os.path.join(paths.run_dir, "enabled")):
+ elif os.path.exists(os.path.join(paths.run_dir, "disabled")):
is_disabled = True
reason = "Cloud-init disabled by cloud-init-generator"
- else:
+ elif os.path.exists(os.path.join(paths.run_dir, "enabled")):
reason = "Cloud-init enabled by systemd cloud-init-generator"
+ else:
+ reason = "Systemd generator may not have run yet."
return (is_disabled, reason)
-def _get_status_details(paths):
+def get_status_details(paths=None):
"""Return a 3-tuple of status, status_details and time of last event.
@param paths: An initialized cloudinit.helpers.paths object.
Values are obtained from parsing paths.run_dir/status.json.
"""
- status = STATUS_ENABLED_NOT_RUN
+ if not paths:
+ init = Init(ds_deps=[])
+ init.read_cfg()
+ paths = init.paths
+
+ status = UXAppStatus.NOT_RUN
status_detail = ""
status_v1 = {}
@@ -126,18 +136,18 @@ def _get_status_details(paths):
CLOUDINIT_DISABLED_FILE, paths
)
if is_disabled:
- status = STATUS_DISABLED
+ status = UXAppStatus.DISABLED
status_detail = reason
if os.path.exists(status_file):
if not os.path.exists(result_file):
- status = STATUS_RUNNING
+ status = UXAppStatus.RUNNING
status_v1 = load_json(load_file(status_file)).get("v1", {})
errors = []
latest_event = 0
for key, value in sorted(status_v1.items()):
if key == "stage":
if value:
- status = STATUS_RUNNING
+ status = UXAppStatus.RUNNING
status_detail = "Running in stage: {0}".format(value)
elif key == "datasource":
status_detail = value
@@ -146,15 +156,15 @@ def _get_status_details(paths):
start = value.get("start") or 0
finished = value.get("finished") or 0
if finished == 0 and start != 0:
- status = STATUS_RUNNING
+ status = UXAppStatus.RUNNING
event_time = max(start, finished)
if event_time > latest_event:
latest_event = event_time
if errors:
- status = STATUS_ERROR
+ status = UXAppStatus.ERROR
status_detail = "\n".join(errors)
- elif status == STATUS_ENABLED_NOT_RUN and latest_event > 0:
- status = STATUS_DONE
+ elif status == UXAppStatus.NOT_RUN and latest_event > 0:
+ status = UXAppStatus.DONE
if latest_event:
time = strftime("%a, %d %b %Y %H:%M:%S %z", gmtime(latest_event))
else: