diff --git a/pmb/config/__init__.py b/pmb/config/__init__.py index f7fdb3d2..fb60705b 100644 --- a/pmb/config/__init__.py +++ b/pmb/config/__init__.py @@ -45,8 +45,8 @@ apk_tools_static_min_version = "2.9.0-r0" work_version = "1" # Only save keys to the config file, which we ask for in 'pmbootstrap init'. -config_keys = ["ccache_size", "device", "extra_packages", "jobs", "keymap", - "nonfree_firmware", "nonfree_userland", +config_keys = ["ccache_size", "device", "extra_packages", "hostname", "jobs", + "keymap", "nonfree_firmware", "nonfree_userland", "qemu_native_mesa_driver", "timezone", "ui", "user", "work"] # Config file/commandline default values @@ -62,6 +62,7 @@ defaults = { "config": os.path.expanduser("~") + "/.config/pmbootstrap.cfg", "device": "samsung-i9100", "extra_packages": "none", + "hostname": "", # A higher value is typically desired, but this can lead to VERY long open # times on slower devices due to host systems being MUCH faster than the # target device: diff --git a/pmb/config/init.py b/pmb/config/init.py index 4db7d4b6..1996e078 100644 --- a/pmb/config/init.py +++ b/pmb/config/init.py @@ -240,6 +240,18 @@ def ask_for_build_options(args, cfg): cfg["pmbootstrap"]["ccache_size"] = answer +def ask_for_hostname(args, device): + while True: + ret = pmb.helpers.cli.ask(args, "Device hostname (short form, e.g. 'foo')", + None, (args.hostname or device), True) + if not pmb.helpers.other.validate_hostname(ret): + continue + # Don't store device name in user's config (gets replaced in install) + if ret == device: + return "" + return ret + + def frontend(args): cfg = pmb.config.load(args) @@ -281,6 +293,9 @@ def frontend(args): # Configure timezone info cfg["pmbootstrap"]["timezone"] = ask_for_timezone(args) + # Hostname + cfg["pmbootstrap"]["hostname"] = ask_for_hostname(args, device) + # Save config pmb.config.save(args, cfg) diff --git a/pmb/helpers/other.py b/pmb/helpers/other.py index d5ed667f..4fdf28bf 100644 --- a/pmb/helpers/other.py +++ b/pmb/helpers/other.py @@ -16,8 +16,9 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with pmbootstrap. If not, see . """ -import os import logging +import os +import re import pmb.chroot import pmb.config import pmb.helpers.run @@ -127,3 +128,26 @@ def migrate_work_folder(args): " folder manually ('sudo rm -rf " + args.work + "') and start over with 'pmbootstrap init'. All your" " binary packages will be lost.") + + +def validate_hostname(hostname): + """ + Check whether the string is a valid hostname, according to + + """ + # Check length + if len(hostname) > 63: + logging.fatal("ERROR: Hostname '" + hostname + "' is too long.") + return False + + # Check that it only contains valid chars + if not re.match("^[0-9a-z-]*$", hostname): + logging.fatal("ERROR: Hostname must only contain letters (a-z)," + " digits (0-9) or minus signs (-)") + return False + + # Check that doesn't begin or end with a minus sign + if hostname[:1] == "-" or hostname[-1:] == "-": + logging.fatal("ERROR: Hostname must not begin or end with a minus sign") + return False + return True diff --git a/pmb/install/_install.py b/pmb/install/_install.py index c8e9ec60..624c965f 100644 --- a/pmb/install/_install.py +++ b/pmb/install/_install.py @@ -18,7 +18,9 @@ along with pmbootstrap. If not, see . """ import logging import os +import re import glob +import shlex import pmb.chroot import pmb.chroot.apk @@ -234,6 +236,28 @@ def setup_keymap(args): logging.info("NOTE: No valid keymap specified for device") +def setup_hostname(args): + """ + Set the hostname and update localhost address in /etc/hosts + """ + # Default to device name + hostname = args.hostname + if not hostname: + hostname = args.device + + if not pmb.helpers.other.validate_hostname(hostname): + raise RuntimeError("Hostname '" + hostname + "' is not valid, please" + " run 'pmbootstrap init' to configure it.") + + # Update /etc/hosts + suffix = "rootfs_" + args.device + pmb.chroot.root(args, ["sh", "-c", "echo " + shlex.quote(hostname) + + " > /etc/hostname"], suffix) + regex = ("s/^127\.0\.0\.1.*/127.0.0.1\t" + re.escape(hostname) + + " localhost.localdomain localhost/") + pmb.chroot.root(args, ["sed", "-i", "-e", regex, "/etc/hosts"], suffix) + + def install_system_image(args): # Partition and fill image/sdcard logging.info("*** (3/5) PREPARE INSTALL BLOCKDEVICE ***") @@ -377,6 +401,9 @@ def install(args): # Set timezone pmb.chroot.root(args, ["setup-timezone", "-z", args.timezone], suffix) + # Set the hostname as the device name + setup_hostname(args) + if args.android_recovery_zip: install_recovery_zip(args) else: diff --git a/test/test_questions.py b/test/test_questions.py index 685c36bf..ee3233df 100644 --- a/test/test_questions.py +++ b/test/test_questions.py @@ -219,3 +219,28 @@ def test_questions_build_options(args, monkeypatch): func(args, cfg) assert cfg == {"pmbootstrap": {"jobs": "5", "ccache_size": "2G"}} + + +def test_questions_hostname(args, monkeypatch): + func = pmb.config.init.ask_for_hostname + device = "test-device" + + # Valid hostname + fake_answers(monkeypatch, ["valid"]) + assert func(args, device) == "valid" + + # Hostname too long ("aaaaa...") + fake_answers(monkeypatch, ["a" * 64, "a" * 63]) + assert func(args, device) == "a" * 63 + + # Fail the regex + fake_answers(monkeypatch, ["$invalid", "valid"]) + assert func(args, device) == "valid" + + # Begins or ends with minus + fake_answers(monkeypatch, ["-invalid", "invalid-", "valid"]) + assert func(args, device) == "valid" + + # Device name: empty string + fake_answers(monkeypatch, [device]) + assert func(args, device) == ""