From f97ac86dc0dadc20b53d66dade311e4b4e50b7fc Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Thu, 31 Oct 2019 18:03:00 -0500 Subject: hscript: Implement fs, add tests --- hscript/disk.cc | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ hscript/disk.hh | 15 +++++++++++++++ hscript/script.cc | 27 ++++++++++++++++++++++++++- 3 files changed, 93 insertions(+), 1 deletion(-) (limited to 'hscript') diff --git a/hscript/disk.cc b/hscript/disk.cc index a54b36d..72604d9 100644 --- a/hscript/disk.cc +++ b/hscript/disk.cc @@ -13,6 +13,7 @@ #include #include /* strerror */ #include +#include #include #ifdef HAS_INSTALL_ENV # include /* assert */ @@ -606,6 +607,57 @@ bool LVMVolume::execute(ScriptOptions) const { } +const static std::set valid_fses = { + "ext2", "ext3", "ext4", "jfs", "vfat", "xfs" +}; + + +Key *Filesystem::parseFromData(const std::string &data, int lineno, + int *errors, int *) { + if(std::count(data.begin(), data.end(), ' ') != 1) { + if(errors) *errors += 1; + output_error("installfile:" + std::to_string(lineno), + "fs: expected exactly two elements", + "syntax is: fs [device] [fstype]"); + return nullptr; + } + + std::string::size_type sep = data.find(' '); + std::string device(data.substr(0, sep)); + std::string fstype(data.substr(sep + 1)); + + if(device.size() < 6 || device.compare(0, 5, "/dev/")) { + if(errors) *errors += 1; + output_error("installfile:" + std::to_string(lineno), + "fs: element 1: expected device node", + "'" + device + "' is not a valid device node"); + return nullptr; + } + + if(valid_fses.find(fstype) == valid_fses.end()) { + std::string fses; + for(auto &&fs : valid_fses) fses += fs + " "; + + if(errors) *errors += 1; + output_error("installfile:" + std::to_string(lineno), + "fs: element 2: expected filesystem type", + "valid filesystems are: " + fses); + return nullptr; + } + + return new Filesystem(lineno, device, fstype); +} + +bool Filesystem::validate(ScriptOptions) const { + /* Validation is done during parsing. */ + return true; +} + +bool Filesystem::execute(ScriptOptions) const { + return false; +} + + Key *Mount::parseFromData(const std::string &data, int lineno, int *errors, int *warnings) { std::string dev, where, opt; diff --git a/hscript/disk.hh b/hscript/disk.hh index 43bb56d..53e2749 100644 --- a/hscript/disk.hh +++ b/hscript/disk.hh @@ -170,6 +170,21 @@ public: }; class Filesystem : public Key { +private: + const std::string _block; + const std::string _type; + + Filesystem(int _line, const std::string &_b, const std::string &_t) : + Key(_line), _block(_b), _type(_t) {} +public: + /*! Retrieve the block device on which to create the filesystem. */ + const std::string device() const { return this->_block; } + /*! Retreive the type of filesystem to create. */ + const std::string fstype() const { return this->_type; } + + static Key *parseFromData(const std::string &, int, int*, int*); + bool validate(ScriptOptions) const override; + bool execute(ScriptOptions) const override; }; class Mount : public Key { diff --git a/hscript/script.cc b/hscript/script.cc index dae014c..050bb01 100644 --- a/hscript/script.cc +++ b/hscript/script.cc @@ -118,6 +118,8 @@ struct Script::ScriptPrivate { std::vector< std::unique_ptr > lvm_vgs; /*! LVM logical volume keys */ std::vector< std::unique_ptr > lvm_lvs; + /*! Filesystem creation keys */ + std::vector< std::unique_ptr > fses; /*! Target system's mountpoints. */ std::vector< std::unique_ptr > mounts; @@ -196,6 +198,10 @@ struct Script::ScriptPrivate { std::unique_ptr lv(dynamic_cast(obj)); this->lvm_lvs.push_back(std::move(lv)); return true; + } else if(key_name == "fs") { + std::unique_ptr fs(dynamic_cast(obj)); + this->fses.push_back(std::move(fs)); + return true; } else if(key_name == "mount") { std::unique_ptr mount(dynamic_cast(obj)); this->mounts.push_back(std::move(mount)); @@ -687,7 +693,7 @@ bool add_default_repos(std::vector> &repos) { bool Script::validate() const { int failures = 0; std::set seen_diskids, seen_labels, seen_parts, seen_pvs, - seen_vg_names, seen_vg_pvs, seen_lvs, seen_mounts; + seen_vg_names, seen_vg_pvs, seen_lvs, seen_fses, seen_mounts; std::map seen_iface; /* REQ: Runner.Validate.network */ @@ -913,6 +919,7 @@ bool Script::validate() const { continue; } + /* REQ: Runner.Validate.lvm_lv.Name */ if(seen_lvs.find(lvpath) != seen_lvs.end()) { failures++; output_error("installfile:" + std::to_string(lv->lineno()), @@ -921,6 +928,7 @@ bool Script::validate() const { } seen_lvs.insert(lvpath); + /* REQ: Runner.Validate.lvm_lv.VolumeGroup */ if(seen_vg_names.find(lv->vg()) == seen_vg_names.end()) { /* Let's make sure it still exists, if we are running in the IE */ if(opts.test(InstallEnvironment)) { @@ -936,6 +944,23 @@ bool Script::validate() const { } } + /* REQ: Runner.Validate.fs */ + for(auto &fs : this->internal->fses) { + if(!fs->validate(this->opts)) { + failures++; + continue; + } + + /* REQ: Runner.Validate.fs.Unique */ + if(seen_fses.find(fs->device()) != seen_fses.end()) { + failures++; + output_error("installfile:" + std::to_string(fs->lineno()), + "fs: a filesystem is already scheduled to be " + "created on " + fs->device()); + } + seen_fses.insert(fs->device()); + } + /* REQ: Runner.Validate.mount */ for(auto &mount : this->internal->mounts) { if(!mount->validate(this->opts)) { -- cgit v1.2.3-60-g2f50