// file : bbot/machine-manifest.cxx -*- C++ -*- // copyright : Copyright (c) 2014-2017 Code Synthesis Ltd // license : TBC; see accompanying LICENSE file #include #include #include using namespace butl; namespace bbot { using parser = manifest_parser; using parsing = manifest_parsing; using serializer = manifest_serializer; using serialization = manifest_serialization; using name_value = manifest_name_value; // machine_type // string to_string (machine_type t) { switch (t) { case machine_type::kvm: return "kvm"; case machine_type::nspawn: return "nspawn"; } assert (false); return string (); } machine_type to_machine_type (const string& t) { if (t == "kvm") return machine_type::kvm; else if (t == "nspawn") return machine_type::nspawn; else throw invalid_argument ("invalid machine type '" + t + "'"); } // machine_manifest // machine_manifest:: machine_manifest (parser& p, bool iu) : machine_manifest (p, p.next (), iu) { // Make sure this is the end. // name_value nv (p.next ()); if (!nv.empty ()) throw parsing (p.name (), nv.name_line, nv.name_column, "single machine manifest expected"); } machine_manifest:: machine_manifest (parser& p, name_value nv, bool iu) { auto bad_name = [&p, &nv] (const string& d) { throw parsing (p.name (), nv.name_line, nv.name_column, d); }; auto bad_value = [&p, &nv] (const string& d) { throw parsing (p.name (), nv.value_line, nv.value_column, d); }; // Make sure this is the start and we support the version. // if (!nv.name.empty ()) bad_name ("start of machine manifest expected"); if (nv.value != "1") bad_value ("unsupported format version"); optional type; for (nv = p.next (); !nv.empty (); nv = p.next ()) { string& n (nv.name); string& v (nv.value); if (n == "id") { if (!id.empty ()) bad_name ("machine id redefinition"); if (v.empty ()) bad_value ("empty machine id"); id = move (v); } else if (n == "name") { if (!name.empty ()) bad_name ("machine name redefinition"); if (v.empty ()) bad_value ("empty machine name"); name = move (v); } else if (n == "summary") { if (!summary.empty ()) bad_name ("machine summary redefinition"); if (v.empty ()) bad_value ("empty machine summary"); summary = move (v); } else if (n == "type") { if (type) bad_name ("machine type redefinition"); try { type = to_machine_type (v); } catch (const invalid_argument&) { bad_value ("invalid machine type"); } } else if (n == "mac") { if (mac) bad_name ("machine mac redefinition"); mac = move (v); } else if (!iu) bad_name ("unknown name '" + n + "' in machine manifest"); } // Verify all non-optional values were specified. // if (id.empty ()) bad_value ("no machine id specified"); if (name.empty ()) bad_value ("no machine name specified"); if (summary.empty ()) bad_value ("no machine summary specified"); if (!type) bad_value ("no machine type specified"); this->type = *type; } void machine_manifest:: serialize (serializer& s) const { // @@ Should we check that all non-optional values are specified and all // values are valid? // s.next ("", "1"); // Start of manifest. s.next ("id", id); s.next ("name", name); s.next ("summary", summary); s.next ("type", to_string (type)); if (mac) s.next ("mac", *mac); s.next ("", ""); // End of manifest. } }