genode/repos/gems/src/app/sculpt_manager/deploy.h

251 lines
6.4 KiB
C++

/*
* \brief Sculpt deploy management
* \author Norman Feske
* \date 2018-04-30
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _DEPLOY_H_
#define _DEPLOY_H_
/* Genode includes */
#include <base/attached_rom_dataspace.h>
#include <os/reporter.h>
/* included from depot_deploy tool */
#include <children.h>
/* local includes */
#include <model/launchers.h>
#include <model/download_queue.h>
#include <types.h>
#include <runtime.h>
#include <managed_config.h>
#include <view/dialog.h>
#include <depot_query.h>
namespace Sculpt { struct Deploy; }
struct Sculpt::Deploy
{
Env &_env;
Allocator &_alloc;
Runtime_info const &_runtime_info;
Dialog::Generator &_dialog_generator;
Runtime_config_generator &_runtime_config_generator;
Depot_query &_depot_query;
Attached_rom_dataspace const &_launcher_listing_rom;
Attached_rom_dataspace const &_blueprint_rom;
Download_queue const &_download_queue;
typedef String<16> Arch;
Arch _arch { };
Child_state cached_depot_rom_state {
"depot_rom", Ram_quota{24*1024*1024}, Cap_quota{200} };
Child_state uncached_depot_rom_state {
"dynamic_depot_rom", Ram_quota{8*1024*1024}, Cap_quota{200} };
/*
* Report written to '/config/managed/deploy'
*
* This report takes the manually maintained '/config/deploy' and the
* interactive state as input.
*/
Expanding_reporter _managed_deploy_config { _env, "config", "deploy_config" };
/* config obtained from '/config/managed/deploy' */
Attached_rom_dataspace _managed_deploy_rom { _env, "config -> managed/deploy" };
void update_managed_deploy_config(Xml_node deploy)
{
/*
* Ignore intermediate states that may occur when manually updating
* the config/deploy configuration. Depending on the tool used,
* the original file may be unlinked before the new version is
* created. The temporary empty configuration must not be applied.
*/
if (deploy.type() == "empty")
return;
_managed_deploy_config.generate([&] (Xml_generator &xml) {
Arch const arch = deploy.attribute_value("arch", Arch());
if (arch.valid())
xml.attribute("arch", arch);
auto append_xml_node = [&] (Xml_node node) {
xml.append("\t");
node.with_raw_node([&] (char const *start, size_t length) {
xml.append(start, length); });
xml.append("\n");
};
/* copy <common_routes> from manual deploy config */
deploy.for_each_sub_node("common_routes", [&] (Xml_node node) {
append_xml_node(node); });
/*
* Copy the <start> node from manual deploy config, unless the
* component was interactively killed by the user.
*/
deploy.for_each_sub_node("start", [&] (Xml_node node) {
Start_name const name = node.attribute_value("name", Start_name());
if (!_runtime_info.abandoned_by_user(name))
append_xml_node(node);
});
/*
* Add start nodes for interactively launched components.
*/
_runtime_info.gen_launched_deploy_start_nodes(xml);
});
}
bool _manual_installation_scheduled = false;
Managed_config<Deploy> _installation {
_env, "installation", "installation", *this, &Deploy::_handle_installation };
void _handle_installation(Xml_node manual_config)
{
_manual_installation_scheduled = manual_config.has_sub_node("archive");
handle_deploy();
}
Depot_deploy::Children _children { _alloc };
bool update_needed() const
{
return _manual_installation_scheduled
|| _children.any_incomplete()
|| _download_queue.any_active_download();
}
void handle_deploy();
void _handle_managed_deploy()
{
_managed_deploy_rom.update();
handle_deploy();
_depot_query.trigger_depot_query();
}
/**
* Call 'fn' for each unsatisfied dependency of the child's 'start' node
*/
template <typename FN>
void _for_each_missing_server(Xml_node start, FN const &fn) const
{
start.for_each_sub_node("route", [&] (Xml_node route) {
route.for_each_sub_node("service", [&] (Xml_node service) {
service.for_each_sub_node("child", [&] (Xml_node child) {
Start_name const name = child.attribute_value("name", Start_name());
/*
* The dependency to the default-fs alias is always
* satisfied during the deploy phase. But it does not
* appear in the runtime-state report.
*/
if (name == "default_fs_rw")
return;
if (!_runtime_info.present_in_runtime(name))
fn(name);
});
});
});
}
/**
* Re-evaluate child dependencies
*
* \return true if any condition has changed and new children may have
* become able to start
*/
bool update_child_conditions();
bool any_unsatisfied_child() const
{
bool all_satisfied = true;
_children.for_each_unsatisfied_child([&] (Xml_node, Xml_node, Start_name const &) {
all_satisfied = false; });
return !all_satisfied;
}
void gen_child_diagnostics(Xml_generator &xml) const;
void gen_runtime_start_nodes(Xml_generator &) const;
Signal_handler<Deploy> _managed_deploy_handler {
_env.ep(), *this, &Deploy::_handle_managed_deploy };
void restart()
{
/* ignore stale query results */
_depot_query.trigger_depot_query();
_children.apply_config(Xml_node("<config/>"));
}
void reattempt_after_installation()
{
_children.reset_incomplete();
handle_deploy();
}
void gen_depot_query(Xml_generator &xml) const
{
_children.gen_queries(xml);
}
void update_installation()
{
/* feed missing packages to installation queue */
if (_installation.try_generate_manually_managed())
return;
_installation.generate([&] (Xml_generator &xml) {
xml.attribute("arch", _arch);
_children.gen_installation_entries(xml);
_download_queue.gen_installation_entries(xml);
});
}
Deploy(Env &env, Allocator &alloc, Runtime_info const &runtime_info,
Dialog::Generator &dialog_generator,
Runtime_config_generator &runtime_config_generator,
Depot_query &depot_query,
Attached_rom_dataspace const &launcher_listing_rom,
Attached_rom_dataspace const &blueprint_rom,
Download_queue const &download_queue)
:
_env(env), _alloc(alloc), _runtime_info(runtime_info),
_dialog_generator(dialog_generator),
_runtime_config_generator(runtime_config_generator),
_depot_query(depot_query),
_launcher_listing_rom(launcher_listing_rom),
_blueprint_rom(blueprint_rom),
_download_queue(download_queue)
{
_managed_deploy_rom.sigh(_managed_deploy_handler);
}
};
#endif /* _DEPLOY_H_ */