Update engine should use the release channel policy if it exists.
The release channel (aka update track) can be specified by a device
policy. When this is the case, the update engine should use the
value specified by the policy instead of the value specified in
/etc/lsb-release.
BUG=chromium-os:17015
TEST=Added two new tests:
- Added test that OmahaRequestParams uses the release channel passed
in to it when the value is valid, and otherwise uses /etc/lsb-release.
- Added test that the update engine correctly picks up the release
channel that's specified by the policy.
Change-Id: I2fe03712220bb3286476b12cd1f1b330ad006d7c
Reviewed-on: http://gerrit.chromium.org/gerrit/5072
Tested-by: Patrick Dubroy <dubroy@chromium.org>
Reviewed-by: Andrew de los Reyes <adlr@chromium.org>
diff --git a/SConstruct b/SConstruct
index 10c8654..d91b365 100644
--- a/SConstruct
+++ b/SConstruct
@@ -203,6 +203,7 @@
gthread-2.0
libpcrecpp
metrics
+ policy
protobuf
pthread
rootdev
diff --git a/omaha_request_params.cc b/omaha_request_params.cc
index 0f5af5b..c4dff9d 100644
--- a/omaha_request_params.cc
+++ b/omaha_request_params.cc
@@ -13,6 +13,7 @@
#include <vector>
#include <base/file_util.h>
+#include <policy/device_policy.h>
#include "update_engine/simple_key_value_store.h"
#include "update_engine/utils.h"
@@ -25,8 +26,6 @@
namespace chromeos_update_engine {
-const char OmahaRequestParams::kUpdateTrackKey[] = "CHROMEOS_RELEASE_TRACK";
-
const char* const OmahaRequestParams::kAppId(
"{87efface-864d-49a5-9bb3-4b050a7c227a}");
const char* const OmahaRequestParams::kOsPlatform("Chrome OS");
@@ -34,12 +33,15 @@
const char* const OmahaRequestParams::kUpdateUrl(
"https://tools.google.com/service/update2");
+const char OmahaRequestParams::kUpdateTrackKey[] = "CHROMEOS_RELEASE_TRACK";
+
OmahaRequestDeviceParams::OmahaRequestDeviceParams() :
force_lock_down_(false),
forced_lock_down_(false) {}
bool OmahaRequestDeviceParams::Init(const std::string& in_app_version,
- const std::string& in_update_url) {
+ const std::string& in_update_url,
+ const std::string& in_release_track) {
bool stateful_override = !ShouldLockDown();
os_platform = OmahaRequestParams::kOsPlatform;
os_version = OmahaRequestParams::kOsVersion;
@@ -53,11 +55,18 @@
NULL,
stateful_override);
app_lang = "en-US";
- app_track = GetLsbValue(
- kUpdateTrackKey,
- "",
- &chromeos_update_engine::OmahaRequestDeviceParams::IsValidTrack,
- true); // stateful_override
+
+ // Determine the release track if it wasn't specified by the caller.
+ if (in_release_track.empty() || !IsValidTrack(in_release_track)) {
+ app_track = GetLsbValue(
+ kUpdateTrackKey,
+ "",
+ &chromeos_update_engine::OmahaRequestDeviceParams::IsValidTrack,
+ true); // stateful_override
+ } else {
+ app_track = in_release_track;
+ }
+
hardware_class = utils::GetHardwareClass();
struct stat stbuf;
@@ -113,7 +122,7 @@
bool OmahaRequestDeviceParams::SetDeviceTrack(const std::string& track) {
OmahaRequestDeviceParams params;
- TEST_AND_RETURN_FALSE(params.Init("", ""));
+ TEST_AND_RETURN_FALSE(params.Init("", "", ""));
return params.SetTrack(track);
}
@@ -121,7 +130,7 @@
OmahaRequestDeviceParams params;
// Note that params.app_track is an empty string if the value in
// lsb-release file is invalid. See Init() for details.
- return params.Init("", "") ? params.app_track : "";
+ return params.Init("", "", "") ? params.app_track : "";
}
string OmahaRequestDeviceParams::GetLsbValue(const string& key,
diff --git a/omaha_request_params.h b/omaha_request_params.h
index edaba67..da091c0 100644
--- a/omaha_request_params.h
+++ b/omaha_request_params.h
@@ -73,7 +73,8 @@
// |in_app_version| or |in_update_url| prevents automatic detection
// of the parameter. Returns true on success, false otherwise.
bool Init(const std::string& in_app_version,
- const std::string& in_update_url);
+ const std::string& in_update_url,
+ const std::string& in_release_track);
// Permanently changes the release track to |track|. Returns true on success,
// false otherwise.
diff --git a/omaha_request_params_unittest.cc b/omaha_request_params_unittest.cc
index 458f582..d59afcd 100644
--- a/omaha_request_params_unittest.cc
+++ b/omaha_request_params_unittest.cc
@@ -47,7 +47,7 @@
bool OmahaRequestDeviceParamsTest::DoTest(OmahaRequestParams* out,
const string& app_version,
const string& omaha_url) {
- bool success = params_.Init(app_version, omaha_url);
+ bool success = params_.Init(app_version, omaha_url, "");
if (out)
*out = params_;
return success;
@@ -326,7 +326,7 @@
OmahaRequestDeviceParams params;
params.set_root(string("./") + kTestDir);
params.SetLockDown(false);
- EXPECT_TRUE(params.Init("", ""));
+ EXPECT_TRUE(params.Init("", "", ""));
params.SetTrack("zootrack");
}
OmahaRequestParams out;
@@ -351,7 +351,7 @@
OmahaRequestDeviceParams params;
params.set_root(string("./") + kTestDir);
params.SetLockDown(false);
- EXPECT_TRUE(params.Init("", ""));
+ EXPECT_TRUE(params.Init("", "", ""));
params.SetTrack("zootrack");
}
OmahaRequestParams out;
@@ -372,7 +372,7 @@
OmahaRequestDeviceParams params;
params.set_root(string("./") + kTestDir);
params.SetLockDown(true);
- EXPECT_TRUE(params.Init("", ""));
+ EXPECT_TRUE(params.Init("", "", ""));
params.SetTrack("zootrack");
}
OmahaRequestParams out;
@@ -421,6 +421,28 @@
EXPECT_EQ("http://www.google.com", out.update_url);
}
+TEST_F(OmahaRequestDeviceParamsTest, ChannelSpecified) {
+ ASSERT_TRUE(WriteFileString(
+ kTestDir + "/etc/lsb-release",
+ "CHROMEOS_RELEASE_BOARD=arm-generic\n"
+ "CHROMEOS_RELEASE_FOO=bar\n"
+ "CHROMEOS_RELEASE_VERSION=0.2.2.3\n"
+ "CHROMEOS_RELEASE_TRACK=dev-channel\n"
+ "CHROMEOS_AUSERVER=http://www.google.com"));
+ params_.SetLockDown(true);
+ // Passed-in value for release channel should be used.
+ params_.Init("", "", "beta-channel");
+ EXPECT_EQ("beta-channel", params_.app_track);
+
+ // When passed-in value is invalid, value from lsb-release should be used.
+ params_.Init("", "", "foo-channel");
+ EXPECT_EQ("dev-channel", params_.app_track);
+
+ // When passed-in value is empty, value from lsb-release should be used.
+ params_.Init("", "", "");
+ EXPECT_EQ("dev-channel", params_.app_track);
+}
+
TEST_F(OmahaRequestDeviceParamsTest, ShouldLockDownTest) {
EXPECT_FALSE(params_.ShouldLockDown());
}
diff --git a/update_attempter.cc b/update_attempter.cc
index 3206067..27d3a91 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -17,6 +17,8 @@
#include <base/rand_util.h>
#include <glib.h>
#include <metrics/metrics_library.h>
+#include <policy/libpolicy.h>
+#include <policy/device_policy.h>
#include "update_engine/dbus_service.h"
#include "update_engine/download_action.h"
@@ -119,7 +121,8 @@
chrome_proxy_resolver_(dbus_iface),
updated_boot_flags_(false),
update_boot_flags_running_(false),
- start_action_processor_(false) {
+ start_action_processor_(false),
+ policy_provider_(NULL) {
if (utils::FileExists(kUpdateCompletedMarker))
status_ = UPDATE_STATUS_UPDATED_NEED_REBOOT;
}
@@ -147,7 +150,20 @@
return;
}
http_response_code_ = 0;
- if (!omaha_request_params_.Init(app_version, omaha_url)) {
+
+ // Lazy initialize the policy provider, or reload the latest policy data.
+ if (!policy_provider_.get()) {
+ policy_provider_.reset(new policy::PolicyProvider());
+ } else {
+ policy_provider_->Reload();
+ }
+
+ // If the release_track is specified by policy, that takes precedence.
+ string release_track;
+ if (policy_provider_->device_policy_is_loaded())
+ policy_provider_->GetDevicePolicy().GetReleaseChannel(&release_track);
+
+ if (!omaha_request_params_.Init(app_version, omaha_url, release_track)) {
LOG(ERROR) << "Unable to initialize Omaha request device params.";
return;
}
diff --git a/update_attempter.h b/update_attempter.h
index 726685e..46dd41c 100644
--- a/update_attempter.h
+++ b/update_attempter.h
@@ -25,6 +25,10 @@
class MetricsLibraryInterface;
struct UpdateEngineService;
+namespace policy {
+ class PolicyProvider;
+}
+
namespace chromeos_update_engine {
class UpdateCheckScheduler;
@@ -140,6 +144,7 @@
FRIEND_TEST(UpdateAttempterTest, CreatePendingErrorEventResumedTest);
FRIEND_TEST(UpdateAttempterTest, DisableDeltaUpdateIfNeededTest);
FRIEND_TEST(UpdateAttempterTest, MarkDeltaUpdateFailureTest);
+ FRIEND_TEST(UpdateAttempterTest, ReadTrackFromPolicy);
FRIEND_TEST(UpdateAttempterTest, PingOmahaTest);
FRIEND_TEST(UpdateAttempterTest, ScheduleErrorEventActionNoEventTest);
FRIEND_TEST(UpdateAttempterTest, ScheduleErrorEventActionTest);
@@ -286,6 +291,9 @@
// True if the action processor needs to be started by the boot flag updater.
bool start_action_processor_;
+ // Used for fetching information about the device policy.
+ scoped_ptr<policy::PolicyProvider> policy_provider_;
+
DISALLOW_COPY_AND_ASSIGN(UpdateAttempter);
};
diff --git a/update_attempter_unittest.cc b/update_attempter_unittest.cc
index b61377b..673471c 100644
--- a/update_attempter_unittest.cc
+++ b/update_attempter_unittest.cc
@@ -4,6 +4,8 @@
#include <base/file_util.h>
#include <gtest/gtest.h>
+#include <policy/libpolicy.h>
+#include <policy/mock_device_policy.h>
#include "update_engine/action_mock.h"
#include "update_engine/action_processor_mock.h"
@@ -60,14 +62,19 @@
attempter_.prefs_ = &prefs_;
}
+ void QuitMainLoop();
+ static gboolean StaticQuitMainLoop(gpointer data);
+
void UpdateTestStart();
void UpdateTestVerify();
static gboolean StaticUpdateTestStart(gpointer data);
static gboolean StaticUpdateTestVerify(gpointer data);
+
void PingOmahaTestStart();
- void PingOmahaTestDone();
static gboolean StaticPingOmahaTestStart(gpointer data);
- static gboolean StaticPingOmahaTestDone(gpointer data);
+
+ void ReadTrackFromPolicyTestStart();
+ static gboolean StaticReadTrackFromPolicyTestStart(gpointer data);
MockDbusGlib dbus_;
UpdateAttempterUnderTest attempter_;
@@ -237,6 +244,15 @@
UpdateStatusToString(static_cast<UpdateStatus>(-1)));
}
+void UpdateAttempterTest::QuitMainLoop() {
+ g_main_loop_quit(loop_);
+}
+
+gboolean UpdateAttempterTest::StaticQuitMainLoop(gpointer data) {
+ reinterpret_cast<UpdateAttempterTest*>(data)->QuitMainLoop();
+ return FALSE;
+}
+
gboolean UpdateAttempterTest::StaticUpdateTestStart(gpointer data) {
reinterpret_cast<UpdateAttempterTest*>(data)->UpdateTestStart();
return FALSE;
@@ -252,8 +268,9 @@
return FALSE;
}
-gboolean UpdateAttempterTest::StaticPingOmahaTestDone(gpointer data) {
- reinterpret_cast<UpdateAttempterTest*>(data)->PingOmahaTestDone();
+gboolean UpdateAttempterTest::StaticReadTrackFromPolicyTestStart(
+ gpointer data) {
+ reinterpret_cast<UpdateAttempterTest*>(data)->ReadTrackFromPolicyTestStart();
return FALSE;
}
@@ -320,11 +337,7 @@
.Times(1);
EXPECT_CALL(*processor_, StartProcessing()).Times(1);
attempter_.PingOmaha();
- g_idle_add(&StaticPingOmahaTestDone, this);
-}
-
-void UpdateAttempterTest::PingOmahaTestDone() {
- g_main_loop_quit(loop_);
+ g_idle_add(&StaticQuitMainLoop, this);
}
TEST_F(UpdateAttempterTest, PingOmahaTest) {
@@ -366,4 +379,32 @@
attempter_.error_event_->error_code);
}
+TEST_F(UpdateAttempterTest, ReadTrackFromPolicy) {
+ loop_ = g_main_loop_new(g_main_context_default(), FALSE);
+ g_idle_add(&StaticReadTrackFromPolicyTestStart, this);
+ g_main_loop_run(loop_);
+ g_main_loop_unref(loop_);
+ loop_ = NULL;
+}
+
+void UpdateAttempterTest::ReadTrackFromPolicyTestStart() {
+ // Tests that the update track (aka release channel) is properly fetched
+ // from the device policy.
+
+ policy::MockDevicePolicy* device_policy = new policy::MockDevicePolicy();
+ attempter_.policy_provider_.reset(new policy::PolicyProvider(device_policy));
+
+ EXPECT_CALL(*device_policy, LoadPolicy()).WillRepeatedly(Return(true));
+
+ EXPECT_CALL(*device_policy, GetReleaseChannel(_))
+ .WillRepeatedly(DoAll(
+ SetArgumentPointee<0>(std::string("canary-channel")),
+ Return(true)));
+
+ attempter_.Update("", "", false, false);
+ EXPECT_EQ("canary-channel", attempter_.omaha_request_params_.app_track);
+
+ g_idle_add(&StaticQuitMainLoop, this);
+}
+
} // namespace chromeos_update_engine