update_engine: Support milestones to EOL from Omaha
Initiative to show EOL message on Chrome OS devices require that
update_engine parses the fields within Omaha response that pertain to the
new milestones to EOL field. The Omaha response will include a new
field called "milestones_to_eol" which will be an integer value
string.
The job of update_engine when it comes to milestones to EOL from Omaha
is to merely forward. No checks and no modifications of fields are
done within update_engine besides being able to convert the milestones
to EOL from a string to integer.
BUG=chromium:994999
TEST=FEATURES="test" emerge-$BOARD update_engine update_engine-client
TEST=cros deploy $IP update_engine update_engine-client
TEST=test_that -b $BOARD $IP autoupdate_EOL # from Cq-Depend
TEST=test_that -b $BOARD $IP autoupdate_EOL.milestones # from Cq-Depend
Cq-Depend:chromium:1761371
Change-Id: I268e4c8e641b17d6a727a50f53285cc97c76eb22
Reviewed-on: https://chromium-review.googlesource.com/1759285
Tested-by: Jae Hoon Kim <kimjae@chromium.org>
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org>
Reviewed-by: Nicolas Norvez <norvez@chromium.org>
Reviewed-by: Amin Hassani <ahassani@chromium.org>
diff --git a/client_library/client_dbus.cc b/client_library/client_dbus.cc
index e2defe7..d0f7f81 100644
--- a/client_library/client_dbus.cc
+++ b/client_library/client_dbus.cc
@@ -270,8 +270,9 @@
return proxy_->GetLastAttemptError(last_attempt_error, nullptr);
}
-bool DBusUpdateEngineClient::GetEolStatus(int32_t* eol_status) const {
- return proxy_->GetEolStatus(eol_status, nullptr);
+bool DBusUpdateEngineClient::GetEolStatus(int32_t* eol_status,
+ int32_t* milestones_to_eol) const {
+ return proxy_->GetEolStatus(eol_status, milestones_to_eol, nullptr);
}
} // namespace internal
diff --git a/client_library/client_dbus.h b/client_library/client_dbus.h
index c9631cf..3f782e9 100644
--- a/client_library/client_dbus.h
+++ b/client_library/client_dbus.h
@@ -85,7 +85,8 @@
bool GetLastAttemptError(int32_t* last_attempt_error) const override;
- bool GetEolStatus(int32_t* eol_status) const override;
+ bool GetEolStatus(int32_t* eol_status,
+ int32_t* milestones_to_eol) const override;
private:
void DBusStatusHandlersRegistered(const std::string& interface,
diff --git a/client_library/include/update_engine/client.h b/client_library/include/update_engine/client.h
index 89f36af..65a3267 100644
--- a/client_library/include/update_engine/client.h
+++ b/client_library/include/update_engine/client.h
@@ -135,8 +135,10 @@
// Get the last UpdateAttempt error code.
virtual bool GetLastAttemptError(int32_t* last_attempt_error) const = 0;
- // Get the current end-of-life status code. See EolStatus enum for details.
- virtual bool GetEolStatus(int32_t* eol_status) const = 0;
+ // Get the current end-of-life status code and milestones to end-of-life.
+ // See |EolStatus| enum and |MilestonesToEol| enum for details.
+ virtual bool GetEolStatus(int32_t* eol_status,
+ int32_t* milestones_to_eol) const = 0;
protected:
// Use CreateInstance().
diff --git a/common/constants.cc b/common/constants.cc
index 87bdf91..6f37e16 100644
--- a/common/constants.cc
+++ b/common/constants.cc
@@ -56,6 +56,7 @@
const char kPrefsOmahaCohortHint[] = "omaha-cohort-hint";
const char kPrefsOmahaCohortName[] = "omaha-cohort-name";
const char kPrefsOmahaEolStatus[] = "omaha-eol-status";
+const char kPrefsOmahaMilestonesToEol[] = "omaha-milestones-to-eol";
const char kPrefsP2PEnabled[] = "p2p-enabled";
const char kPrefsP2PFirstAttemptTimestamp[] = "p2p-first-attempt-timestamp";
const char kPrefsP2PNumAttempts[] = "p2p-num-attempts";
diff --git a/common/constants.h b/common/constants.h
index d95a56a..6034dbd 100644
--- a/common/constants.h
+++ b/common/constants.h
@@ -57,6 +57,7 @@
extern const char kPrefsOmahaCohortHint[];
extern const char kPrefsOmahaCohortName[];
extern const char kPrefsOmahaEolStatus[];
+extern const char kPrefsOmahaMilestonesToEol[];
extern const char kPrefsP2PEnabled[];
extern const char kPrefsP2PFirstAttemptTimestamp[];
extern const char kPrefsP2PNumAttempts[];
diff --git a/common_service.cc b/common_service.cc
index 0d5ee6d..466007f 100644
--- a/common_service.cc
+++ b/common_service.cc
@@ -413,18 +413,31 @@
}
bool UpdateEngineService::GetEolStatus(ErrorPtr* error,
- int32_t* out_eol_status) {
+ int32_t* out_eol_status,
+ int32_t* out_milestones_to_eol) {
PrefsInterface* prefs = system_state_->prefs();
+ // Set EOL.
string str_eol_status;
if (prefs->Exists(kPrefsOmahaEolStatus) &&
!prefs->GetString(kPrefsOmahaEolStatus, &str_eol_status)) {
LogAndSetError(error, FROM_HERE, "Error getting the end-of-life status.");
return false;
}
-
- // StringToEolStatus will return kSupported for invalid values.
+ // |StringToEolStatus()| will return |kSupported| for invalid values.
*out_eol_status = static_cast<int32_t>(StringToEolStatus(str_eol_status));
+
+ // Set milestones to EOL.
+ string str_milestones_to_eol;
+ if (prefs->Exists(kPrefsOmahaMilestonesToEol) &&
+ !prefs->GetString(kPrefsOmahaMilestonesToEol, &str_milestones_to_eol)) {
+ LogAndSetError(error, FROM_HERE, "Error getting the milestones to EOL.");
+ return false;
+ }
+ // |StringToMilestonesToEol()| will return |kMilestonesToEolNone| for invalid
+ // values.
+ *out_milestones_to_eol = StringToMilestonesToEol(str_milestones_to_eol);
+
return true;
}
diff --git a/common_service.h b/common_service.h
index f93855d..5244e99 100644
--- a/common_service.h
+++ b/common_service.h
@@ -153,9 +153,12 @@
bool GetLastAttemptError(brillo::ErrorPtr* error,
int32_t* out_last_attempt_error);
- // Returns the current end-of-life status of the device. This value is updated
- // on every update check and persisted on disk across reboots.
- bool GetEolStatus(brillo::ErrorPtr* error, int32_t* out_eol_status);
+ // Returns the current EOL status of the device and the milestones to
+ // EOL if marked EOL. The values are updated on every update check and
+ // persisted on disk across reboots.
+ bool GetEolStatus(brillo::ErrorPtr* error,
+ int32_t* out_eol_status,
+ int32_t* out_milestones_to_eol);
private:
SystemState* system_state_;
diff --git a/common_service_unittest.cc b/common_service_unittest.cc
index 65202a0..68b2468 100644
--- a/common_service_unittest.cc
+++ b/common_service_unittest.cc
@@ -169,19 +169,90 @@
UpdateEngineService::kErrorFailed));
}
-TEST_F(UpdateEngineServiceTest, GetEolStatusTest) {
+TEST_F(UpdateEngineServiceTest, GetEolStatusTestWithMilestonesDefault) {
FakePrefs fake_prefs;
fake_system_state_.set_prefs(&fake_prefs);
- // The default value should be "supported".
+ // The default value for EOL be |kSupported| and milestone
+ // |kMilestonesToEolNone|.
int32_t eol_status = static_cast<int32_t>(EolStatus::kEol);
- EXPECT_TRUE(common_service_.GetEolStatus(&error_, &eol_status));
+ MilestonesToEol milestones_to_eol = kMilestonesToEolNone;
+ EXPECT_TRUE(
+ common_service_.GetEolStatus(&error_, &eol_status, &milestones_to_eol));
EXPECT_EQ(nullptr, error_);
EXPECT_EQ(EolStatus::kSupported, static_cast<EolStatus>(eol_status));
+ EXPECT_EQ(kMilestonesToEolNone, milestones_to_eol);
+}
- fake_prefs.SetString(kPrefsOmahaEolStatus, "security-only");
- EXPECT_TRUE(common_service_.GetEolStatus(&error_, &eol_status));
+TEST_F(UpdateEngineServiceTest, GetEolStatusMilestonesToEolNone) {
+ FakePrefs fake_prefs;
+ fake_system_state_.set_prefs(&fake_prefs);
+ int32_t eol_status = static_cast<int32_t>(EolStatus::kEol);
+ MilestonesToEol milestones_to_eol = kMilestonesToEolNone;
+
+ // Device is supported and no milestones to EOL set.
+ fake_prefs.SetString(kPrefsOmahaEolStatus, kEolStatusSupported);
+ EXPECT_TRUE(
+ common_service_.GetEolStatus(&error_, &eol_status, &milestones_to_eol));
+ EXPECT_EQ(nullptr, error_);
+ EXPECT_EQ(EolStatus::kSupported, static_cast<EolStatus>(eol_status));
+ EXPECT_EQ(kMilestonesToEolNone, milestones_to_eol);
+
+ // Device is security only and no milestones to EOL set.
+ fake_prefs.SetString(kPrefsOmahaEolStatus, kEolStatusSecurityOnly);
+ EXPECT_TRUE(
+ common_service_.GetEolStatus(&error_, &eol_status, &milestones_to_eol));
EXPECT_EQ(nullptr, error_);
EXPECT_EQ(EolStatus::kSecurityOnly, static_cast<EolStatus>(eol_status));
+ EXPECT_EQ(kMilestonesToEolNone, milestones_to_eol);
+
+ // Device is EOL and no milestones to EOL set.
+ fake_prefs.SetString(kPrefsOmahaEolStatus, kEolStatusEol);
+ EXPECT_TRUE(
+ common_service_.GetEolStatus(&error_, &eol_status, &milestones_to_eol));
+ EXPECT_EQ(nullptr, error_);
+ EXPECT_EQ(EolStatus::kEol, static_cast<EolStatus>(eol_status));
+ EXPECT_EQ(kMilestonesToEolNone, milestones_to_eol);
+}
+
+TEST_F(UpdateEngineServiceTest, GetEolStatusMilestonesToEolTwo) {
+ FakePrefs fake_prefs;
+ fake_system_state_.set_prefs(&fake_prefs);
+ int32_t eol_status = static_cast<int32_t>(EolStatus::kEol);
+ MilestonesToEol milestones_to_eol = kMilestonesToEolNone;
+
+ // Device is supported and milestones to EOL is n-2.
+ fake_prefs.SetString(kPrefsOmahaEolStatus, kEolStatusSupported);
+ fake_prefs.SetString(kPrefsOmahaMilestonesToEol, "2");
+ EXPECT_TRUE(
+ common_service_.GetEolStatus(&error_, &eol_status, &milestones_to_eol));
+ EXPECT_EQ(nullptr, error_);
+ EXPECT_EQ(EolStatus::kSupported, static_cast<EolStatus>(eol_status));
+ EXPECT_EQ(2, milestones_to_eol);
+
+ // Device is security only and milestones to EOL is n-2.
+ fake_prefs.SetString(kPrefsOmahaEolStatus, kEolStatusSecurityOnly);
+ fake_prefs.SetString(kPrefsOmahaMilestonesToEol, "2");
+ EXPECT_TRUE(
+ common_service_.GetEolStatus(&error_, &eol_status, &milestones_to_eol));
+ EXPECT_EQ(nullptr, error_);
+ EXPECT_EQ(EolStatus::kSecurityOnly, static_cast<EolStatus>(eol_status));
+ EXPECT_EQ(2, milestones_to_eol);
+}
+
+TEST_F(UpdateEngineServiceTest, GetEolStatusMilestonesToEolZero) {
+ FakePrefs fake_prefs;
+ fake_system_state_.set_prefs(&fake_prefs);
+ int32_t eol_status = static_cast<int32_t>(EolStatus::kEol);
+ MilestonesToEol milestones_to_eol = kMilestonesToEolNone;
+
+ // Device is EOL and milestones to EOL is n.
+ fake_prefs.SetString(kPrefsOmahaEolStatus, kEolStatusEol);
+ fake_prefs.SetString(kPrefsOmahaMilestonesToEol, "0");
+ EXPECT_TRUE(
+ common_service_.GetEolStatus(&error_, &eol_status, &milestones_to_eol));
+ EXPECT_EQ(nullptr, error_);
+ EXPECT_EQ(EolStatus::kEol, static_cast<EolStatus>(eol_status));
+ EXPECT_EQ(0, milestones_to_eol);
}
} // namespace chromeos_update_engine
diff --git a/dbus_bindings/org.chromium.UpdateEngineInterface.dbus-xml b/dbus_bindings/org.chromium.UpdateEngineInterface.dbus-xml
index a183147..5671fde 100644
--- a/dbus_bindings/org.chromium.UpdateEngineInterface.dbus-xml
+++ b/dbus_bindings/org.chromium.UpdateEngineInterface.dbus-xml
@@ -139,6 +139,7 @@
</method>
<method name="GetEolStatus">
<arg type="i" name="eol_status" direction="out" />
+ <arg type="i" name="milestones_to_eol" direction="out" />
</method>
</interface>
</node>
diff --git a/dbus_service.cc b/dbus_service.cc
index b379603..168265d 100644
--- a/dbus_service.cc
+++ b/dbus_service.cc
@@ -212,8 +212,9 @@
}
bool DBusUpdateEngineService::GetEolStatus(ErrorPtr* error,
- int32_t* out_eol_status) {
- return common_->GetEolStatus(error, out_eol_status);
+ int32_t* out_eol_status,
+ int32_t* out_milestone_to_eol) {
+ return common_->GetEolStatus(error, out_eol_status, out_milestone_to_eol);
}
UpdateEngineAdaptor::UpdateEngineAdaptor(SystemState* system_state)
diff --git a/dbus_service.h b/dbus_service.h
index 2babf8c..9d79609 100644
--- a/dbus_service.h
+++ b/dbus_service.h
@@ -157,8 +157,13 @@
bool GetLastAttemptError(brillo::ErrorPtr* error,
int32_t* out_last_attempt_error) override;
- // Returns the current end-of-life status of the device in |out_eol_status|.
- bool GetEolStatus(brillo::ErrorPtr* error, int32_t* out_eol_status) override;
+ // Returns the current EOL status of the device in |out_eol_status| and the
+ // milestones to EOL of the device in |out_milestones_to_eol| for EOL devices.
+ // In the case that milestones to EOL doesn't exists for EOL, it will default
+ // to |kMilestonesToEolNone|.
+ bool GetEolStatus(brillo::ErrorPtr* error,
+ int32_t* out_eol_status,
+ int32_t* out_milestones_to_eol) override;
private:
std::unique_ptr<UpdateEngineService> common_;
diff --git a/omaha_request_action.cc b/omaha_request_action.cc
index 6c67a3b..8da7e29 100644
--- a/omaha_request_action.cc
+++ b/omaha_request_action.cc
@@ -109,6 +109,7 @@
// updatecheck attributes (without the underscore prefix).
constexpr char kAttrEol[] = "eol";
+constexpr char kAttrMilestonesToEol[] = "milestones_to_eol";
constexpr char kAttrRollback[] = "rollback";
constexpr char kAttrFirmwareVersion[] = "firmware_version";
constexpr char kAttrKernelVersion[] = "kernel_version";
@@ -1315,13 +1316,28 @@
bool OmahaRequestAction::PersistEolStatus(const map<string, string>& attrs) {
auto eol_attr = attrs.find(kAttrEol);
- if (eol_attr != attrs.end()) {
- return system_state_->prefs()->SetString(kPrefsOmahaEolStatus,
- eol_attr->second);
- } else if (system_state_->prefs()->Exists(kPrefsOmahaEolStatus)) {
- return system_state_->prefs()->Delete(kPrefsOmahaEolStatus);
+ auto milestones_to_eol_attr = attrs.find(kAttrMilestonesToEol);
+
+ bool ret = true;
+ if (milestones_to_eol_attr == attrs.end()) {
+ system_state_->prefs()->Delete(kPrefsOmahaMilestonesToEol);
+ if (eol_attr != attrs.end()) {
+ LOG(WARNING) << "Milestones to EOL missing when EOL.";
+ }
+ } else if (!system_state_->prefs()->SetString(
+ kPrefsOmahaMilestonesToEol, milestones_to_eol_attr->second)) {
+ LOG(ERROR) << "Setting milestones to EOL failed.";
+ ret = false;
}
- return true;
+
+ if (eol_attr == attrs.end()) {
+ system_state_->prefs()->Delete(kPrefsOmahaEolStatus);
+ } else if (!system_state_->prefs()->SetString(kPrefsOmahaEolStatus,
+ eol_attr->second)) {
+ LOG(ERROR) << "Setting EOL failed.";
+ ret = false;
+ }
+ return ret;
}
void OmahaRequestAction::ActionCompleted(ErrorCode code) {
diff --git a/omaha_request_action.h b/omaha_request_action.h
index 8dffb5c..0c256a8 100644
--- a/omaha_request_action.h
+++ b/omaha_request_action.h
@@ -144,6 +144,7 @@
GetInstallDateWhenOOBECompletedWithValidDate);
FRIEND_TEST(OmahaRequestActionTest,
GetInstallDateWhenOOBECompletedDateChanges);
+ FRIEND_TEST(OmahaRequestActionTest, PersistEolStatusTest);
friend class UpdateAttempterTest;
FRIEND_TEST(UpdateAttempterTest, SessionIdTestEnforceEmptyStrPingOmaha);
FRIEND_TEST(UpdateAttempterTest, SessionIdTestConsistencyInUpdateFlow);
@@ -188,8 +189,9 @@
bool PersistCohortData(const std::string& prefs_key,
const std::string& new_value);
- // Parse and persist the end-of-life status flag sent back in the updatecheck
- // tag attributes. The flag will be validated and stored in the Prefs.
+ // Parse and persist the end-of-life status flag and milestones to EOL sent
+ // back in the updatecheck tag attributes. The flag will be validated and
+ // stored in the Prefs.
bool PersistEolStatus(const std::map<std::string, std::string>& attrs);
// If this is an update check request, initializes
diff --git a/omaha_request_action_unittest.cc b/omaha_request_action_unittest.cc
index 8008e00..11633b6 100644
--- a/omaha_request_action_unittest.cc
+++ b/omaha_request_action_unittest.cc
@@ -2012,6 +2012,65 @@
EXPECT_EQ("security-only", eol_pref);
}
+TEST_F(OmahaRequestActionTest, ParseUpdateCheckAttributesEolTest) {
+ tuc_params_.http_response =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><response "
+ "protocol=\"3.0\"><app appid=\"foo\" status=\"ok\">"
+ "<ping status=\"ok\"/><updatecheck status=\"noupdate\" "
+ "_eol=\"eol\" _milestones_to_eol=\"0\" _foo=\"bar\"/></app></response>";
+ tuc_params_.expected_check_result = metrics::CheckResult::kNoUpdateAvailable;
+ tuc_params_.expected_check_reaction = metrics::CheckReaction::kUnset;
+
+ ASSERT_TRUE(TestUpdateCheck());
+
+ string eol_pref, milestones_to_eol_pref;
+ EXPECT_TRUE(
+ fake_system_state_.prefs()->GetString(kPrefsOmahaEolStatus, &eol_pref));
+ EXPECT_EQ("eol", eol_pref);
+ EXPECT_TRUE(fake_system_state_.prefs()->GetString(kPrefsOmahaMilestonesToEol,
+ &milestones_to_eol_pref));
+ EXPECT_EQ("0", milestones_to_eol_pref);
+}
+
+TEST_F(OmahaRequestActionTest,
+ ParseUpdateCheckAttributesMissingMilestonesToEolTest) {
+ tuc_params_.http_response =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><response "
+ "protocol=\"3.0\"><app appid=\"foo\" status=\"ok\">"
+ "<ping status=\"ok\"/><updatecheck status=\"noupdate\" "
+ "_eol=\"eol\"/></app></response>";
+ tuc_params_.expected_check_result = metrics::CheckResult::kNoUpdateAvailable;
+ tuc_params_.expected_check_reaction = metrics::CheckReaction::kUnset;
+
+ ASSERT_TRUE(TestUpdateCheck());
+
+ string eol_pref, milestones_to_eol_pref;
+ EXPECT_TRUE(
+ fake_system_state_.prefs()->GetString(kPrefsOmahaEolStatus, &eol_pref));
+ EXPECT_EQ("eol", eol_pref);
+ EXPECT_FALSE(fake_system_state_.prefs()->Exists(kPrefsOmahaMilestonesToEol));
+}
+
+TEST_F(OmahaRequestActionTest, ParseUpdateCheckAttributesMilestonesToEolTest) {
+ tuc_params_.http_response =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><response "
+ "protocol=\"3.0\"><app appid=\"foo\" status=\"ok\">"
+ "<ping status=\"ok\"/><updatecheck status=\"noupdate\" "
+ "_eol=\"supported\" _milestones_to_eol=\"3\"/></app></response>";
+ tuc_params_.expected_check_result = metrics::CheckResult::kNoUpdateAvailable;
+ tuc_params_.expected_check_reaction = metrics::CheckReaction::kUnset;
+
+ ASSERT_TRUE(TestUpdateCheck());
+
+ string eol_pref, milestones_to_eol_pref;
+ EXPECT_TRUE(
+ fake_system_state_.prefs()->GetString(kPrefsOmahaEolStatus, &eol_pref));
+ EXPECT_EQ("supported", eol_pref);
+ EXPECT_TRUE(fake_system_state_.prefs()->GetString(kPrefsOmahaMilestonesToEol,
+ &milestones_to_eol_pref));
+ EXPECT_EQ("3", milestones_to_eol_pref);
+}
+
TEST_F(OmahaRequestActionTest, NoUniqueIDTest) {
tuc_params_.http_response = "invalid xml>";
tuc_params_.expected_code = ErrorCode::kOmahaRequestXMLParseError;
diff --git a/omaha_utils.cc b/omaha_utils.cc
index 6bd7525..dffa5d3 100644
--- a/omaha_utils.cc
+++ b/omaha_utils.cc
@@ -17,17 +17,15 @@
#include "update_engine/omaha_utils.h"
#include <base/logging.h>
+#include <base/strings/string_number_conversions.h>
namespace chromeos_update_engine {
-namespace {
-
-// The possible string values for the end-of-life status.
const char kEolStatusSupported[] = "supported";
const char kEolStatusSecurityOnly[] = "security-only";
const char kEolStatusEol[] = "eol";
-} // namespace
+const MilestonesToEol kMilestonesToEolNone = -1;
const char* EolStatusToString(EolStatus eol_status) {
switch (eol_status) {
@@ -50,8 +48,23 @@
return EolStatus::kSecurityOnly;
if (eol_status == kEolStatusEol)
return EolStatus::kEol;
- LOG(WARNING) << "Invalid end-of-life attribute: " << eol_status;
+ LOG(WARNING) << "Invalid EOL attribute: " << eol_status;
return EolStatus::kSupported;
}
+std::string MilestonesToEolToString(MilestonesToEol milestones_to_eol) {
+ return base::IntToString(milestones_to_eol);
+}
+
+MilestonesToEol StringToMilestonesToEol(const std::string& milestones_to_eol) {
+ MilestonesToEol milestone = kMilestonesToEolNone;
+ if (!base::StringToInt(milestones_to_eol, &milestone)) {
+ LOG(WARNING) << "Invalid milestones to EOL attribute: "
+ << milestones_to_eol;
+ return kMilestonesToEolNone;
+ }
+
+ return milestone;
+}
+
} // namespace chromeos_update_engine
diff --git a/omaha_utils.h b/omaha_utils.h
index 8614540..6000451 100644
--- a/omaha_utils.h
+++ b/omaha_utils.h
@@ -21,6 +21,11 @@
namespace chromeos_update_engine {
+// The possible string values for the end-of-life status.
+extern const char kEolStatusSupported[];
+extern const char kEolStatusSecurityOnly[];
+extern const char kEolStatusEol[];
+
// The end-of-life status of the device.
enum class EolStatus {
kSupported = 0,
@@ -28,6 +33,10 @@
kEol,
};
+using MilestonesToEol = int;
+// The default milestones to EOL.
+extern const MilestonesToEol kMilestonesToEolNone;
+
// Returns the string representation of the |eol_status|.
const char* EolStatusToString(EolStatus eol_status);
@@ -35,6 +44,14 @@
// of an invalid string, the default "supported" value will be used instead.
EolStatus StringToEolStatus(const std::string& eol_status);
+// Returns the string representation of the |milestones_to_eol|.
+std::string MilestonesToEolToString(int milestones_to_eol);
+
+// Converts the milestones to EOL string to an |MilestonesToEol| enum class.
+// When the milestones to EOL is not an integer, the default
+// |kMilestonesToEolNone| will be returned.
+MilestonesToEol StringToMilestonesToEol(const std::string& milestones_to_eol);
+
} // namespace chromeos_update_engine
#endif // UPDATE_ENGINE_OMAHA_UTILS_H_
diff --git a/omaha_utils_unittest.cc b/omaha_utils_unittest.cc
index 8ceb76b..59c0366 100644
--- a/omaha_utils_unittest.cc
+++ b/omaha_utils_unittest.cc
@@ -39,4 +39,12 @@
EXPECT_EQ(EolStatus::kSupported, StringToEolStatus("hello, world!"));
}
+TEST(OmahaUtilsTest, MilestonesToEolTest) {
+ EXPECT_EQ(kMilestonesToEolNone, StringToMilestonesToEol(""));
+ EXPECT_EQ(kMilestonesToEolNone, StringToMilestonesToEol("not_a_number"));
+ EXPECT_EQ(1, StringToMilestonesToEol("1"));
+ EXPECT_EQ(0, StringToMilestonesToEol("0"));
+ EXPECT_EQ(-1, StringToMilestonesToEol("-1"));
+}
+
} // namespace chromeos_update_engine
diff --git a/update_engine_client.cc b/update_engine_client.cc
index 954e856..9748c4d 100644
--- a/update_engine_client.cc
+++ b/update_engine_client.cc
@@ -41,6 +41,7 @@
using chromeos_update_engine::EolStatus;
using chromeos_update_engine::ErrorCode;
+using chromeos_update_engine::MilestonesToEol;
using chromeos_update_engine::UpdateEngineStatusToString;
using chromeos_update_engine::UpdateStatusToString;
using chromeos_update_engine::utils::ErrorCodeToString;
@@ -559,12 +560,20 @@
}
if (FLAGS_eol_status) {
- int eol_status;
- if (!client_->GetEolStatus(&eol_status)) {
- LOG(ERROR) << "Error getting the end-of-life status.";
+ int eol_status, milestones_to_eol;
+ if (!client_->GetEolStatus(&eol_status, &milestones_to_eol)) {
+ LOG(ERROR) << "Error getting the end-of-life status and milestones to "
+ "end-of-life.";
} else {
EolStatus eol_status_code = static_cast<EolStatus>(eol_status);
- printf("EOL_STATUS=%s\n", EolStatusToString(eol_status_code));
+ MilestonesToEol milestones_to_eol_code = milestones_to_eol;
+ printf(
+ "EOL_STATUS=%s\n"
+ "MILESTONES_TO_EOL=%s\n",
+ EolStatusToString(eol_status_code),
+ chromeos_update_engine::MilestonesToEolToString(
+ milestones_to_eol_code)
+ .c_str());
}
}