def test_save_keep_other_options(tmpdir): path = create_lvm_conf(tmpdir, CONF) with lvmconf.LVMConfig(path) as conf: conf.setlist("devices", "filter", ["a|.*|"]) conf.save() with lvmconf.LVMConfig(path) as conf: assert conf.getint("global", "use_lvmetad") == 1
def test_set_empty_list(tmpdir): path = create_lvm_conf(tmpdir, CONF) with lvmconf.LVMConfig(path) as conf: conf.setlist("devices", "filter", []) conf.save() with lvmconf.LVMConfig(path) as conf: assert conf.getlist("devices", "filter") is None
def test_remove(tmpdir): path = create_lvm_conf(tmpdir, CONF) with lvmconf.LVMConfig(path) as conf: conf.remove("devices", "filter") conf.save() with lvmconf.LVMConfig(path) as conf: assert conf.getlist("devices", "filter") is None
def test_save_backup(tmpdir): path = create_lvm_conf(tmpdir, CONF) with lvmconf.LVMConfig(path) as conf: old_filter = conf.getlist("devices", "filter") conf.setlist("devices", "filter", ["a|.*|"]) conf.save() with lvmconf.LVMConfig(path + ".augsave") as backup: assert backup.getlist("devices", "filter") == old_filter
def test_save(tmpdir, data): path = create_lvm_conf(tmpdir, data) new_list = ["a|^/dev/sda2$|", "a|^/dev/sdb3$|", "r|.*|"] new_int = 0 new_str = "ignore" with lvmconf.LVMConfig(path) as conf: conf.setlist("devices", "filter", new_list) conf.setint("global", "use_lvmetad", new_int) conf.setstr("activation", "missing_stripe_filler", new_str) conf.save() with lvmconf.LVMConfig(path) as conf: assert conf.getlist("devices", "filter") == new_list assert conf.getint("global", "use_lvmetad") == new_int assert conf.getstr("activation", "missing_stripe_filler") == new_str
def _configure_devices_file(enable=True): """ Configure lvm to use devices file or disable it. """ enabled = 1 if enable else 0 with lvmconf.LVMConfig() as config: config.setint("devices", "use_devicesfile", enabled) config.save()
def _enabled(): """ Return True if lvm is configured to use devices file. Devices file itself is not needed to be configured as it has predefined value by lvm. """ with lvmconf.LVMConfig() as config: use_devicesfile = config.getint("devices", "use_devicesfile") == 1 return use_devicesfile
def remove_filter(): """ Remove LVM filter from LVM configuration file. """ with lvmconf.LVMConfig() as config: current_filter = config.getlist("devices", "filter") if current_filter: config.remove("devices", "filter") config.save()
def test_read_empty(tmpdir): path = create_lvm_conf(tmpdir, "") with lvmconf.LVMConfig(path) as conf: # No option - and no type information assert conf.getlist("devices", "filter") is None assert conf.getint("devices", "filter") is None assert conf.getstr("devices", "filter") is None # Commented is same as no option assert conf.getlist("devices", "global_filter") is None
def test_context_exit_error(tmpdir): # Raise if __exit__ fails. path = create_lvm_conf(tmpdir, "") def fail(): raise RuntimeError with pytest.raises(RuntimeError): with lvmconf.LVMConfig(path) as conf: conf.close = fail
def test_save_error(tmpdir): path = create_lvm_conf(tmpdir, CONF) with lvmconf.LVMConfig(path) as conf: conf.setlist("devices", "filter", ["a|.*|"]) # Make save fail even when runing as root. os.unlink(path) os.mkdir(path) with pytest.raises(EnvironmentError): conf.save()
def config_with_filter(args): mounts = lvmfilter.find_lvm_mounts() wanted_wwids = lvmfilter.find_wwids(mounts) current_wwids = mpathconf.read_blacklist() wanted_filter = lvmfilter.build_filter(mounts) with lvmconf.LVMConfig() as lvm_config: current_filter = lvm_config.getlist("devices", "filter") advice = lvmfilter.analyze( current_filter, wanted_filter, current_wwids, wanted_wwids) # This is the expected condition on a correctly configured host. if advice.action == lvmfilter.UNNEEDED: print("LVM filter is already configured for Vdsm") return # We need to configure LVM filter. _print_summary(mounts, current_filter, wanted_filter, advice.wwids, None) if advice.action == lvmfilter.CONFIGURE: if not args.assume_yes: if not common.confirm("Configure host? [yes,NO] "): return NEEDS_CONFIG mpathconf.configure_blacklist(advice.wwids) with lvmconf.LVMConfig() as config: config.setlist("devices", "filter", advice.filter) config.setint("devices", "use_devicesfile", 0) config.save() _print_success() elif advice.action == lvmfilter.RECOMMEND: _print_filter_warning() return CANNOT_CONFIG
def test_context_propagate_user_error(tmpdir): # Raise user errors if __exit__ fails. path = create_lvm_conf(tmpdir, "") def fail(): raise RuntimeError class UserError(Exception): pass with pytest.raises(UserError): with lvmconf.LVMConfig(path) as conf: conf.close = fail raise UserError
def test_read_options(tmpdir): path = create_lvm_conf(tmpdir, CONF) with lvmconf.LVMConfig(path) as conf: # Correct type assert conf.getlist("devices", "filter") == ["a|^/dev/sda2$|", "r|.*|"] assert conf.getint("global", "use_lvmetad") == 1 assert conf.getstr("activation", "missing_stripe_filler") == "error" # Wrong type assert conf.getstr("devices", "filter") is None assert conf.getint("devices", "filter") is None assert conf.getlist("global", "use_lvmetad") is None assert conf.getstr("global", "use_lvmetad") is None assert conf.getint("activation", "missing_stripe_filler") is None assert conf.getlist("activation", "missing_stripe_filler") is None
def main(*args): """ config-lvm-filter Configure LVM filter allowing LVM to access only the local storage needed by the hypervisor, but not shared storage owned by Vdsm. """ print("Analyzing host...") mounts = lvmfilter.find_lvm_mounts() wanted_filter = lvmfilter.build_filter(mounts) with lvmconf.LVMConfig() as config: current_filter = config.getlist("devices", "filter") advice = lvmfilter.analyze(current_filter, wanted_filter) # This is the expected condition on a correctly configured host. if advice.action == lvmfilter.UNNEEDED: print("LVM filter is already configured for Vdsm") return # We need to configure LVM filter. print("Found these mounted logical volumes on this host:") print() for mnt in mounts: print(" logical volume: ", mnt.lv) print(" mountpoint: ", mnt.mountpoint) print(" devices: ", ", ".join(mnt.devices)) print() print("This is the recommended LVM filter for this host:") print() print(" " + lvmfilter.format_option(wanted_filter)) print() print("""\ This filter allows LVM to access the local devices used by the hypervisor, but not shared storage owned by Vdsm. If you add a new device to the volume group, you will need to edit the filter manually. """) if current_filter: print("This is the current LVM filter:") print() print(" " + lvmfilter.format_option(current_filter)) print() if advice.action == lvmfilter.CONFIGURE: if not confirm("Configure LVM filter? [yes,NO] "): return with lvmconf.LVMConfig() as config: config.setlist("devices", "filter", advice.filter) config.save() print("""\ Configuration completed successfully! Please reboot to verify the LVM configuration. """) elif advice.action == lvmfilter.RECOMMEND: print("""\ WARNING: The current LVM filter does not match the recommended filter, Vdsm cannot configure the filter automatically. Please edit /etc/lvm/lvm.conf and set the 'filter' option in the 'devices' section to the recommended value. It is recommend to reboot after changing LVM filter. """)
def test_real_lvm_conf(): with lvmconf.LVMConfig() as conf: assert conf.getint("global", "use_lvmetad") in (1, 0, None)
def main(*args): """ config-lvm-filter Configure LVM filter allowing LVM to access only the local storage needed by the hypervisor, but not shared storage owned by Vdsm. Return codes: 0 - Successful completion. 1 - Exception caught during operation. 2 - Wrong arguments. 3 - LVM filter configuration was found to be required but could not be completed since there is already another filter configured on the host. 4 - User has chosen not to allow LVM filter reconfiguration, although found as required. """ args = parse_args(args) print("Analyzing host...") mounts = lvmfilter.find_lvm_mounts() wanted_filter = lvmfilter.build_filter(mounts) wanted_wwids = lvmfilter.find_wwids(mounts) with lvmconf.LVMConfig() as config: current_filter = config.getlist("devices", "filter") current_wwids = mpathconf.read_blacklist() advice = lvmfilter.analyze( current_filter, wanted_filter, current_wwids, wanted_wwids) # This is the expected condition on a correctly configured host. if advice.action == lvmfilter.UNNEEDED: print("LVM filter is already configured for Vdsm") return # We need to configure LVM filter. print("Found these mounted logical volumes on this host:") print() for mnt in mounts: print(" logical volume: ", mnt.lv) print(" mountpoint: ", mnt.mountpoint) print(" devices: ", ", ".join(mnt.devices)) print() print("This is the recommended LVM filter for this host:") print() print(" " + lvmfilter.format_option(wanted_filter)) print() print("""\ This filter allows LVM to access the local devices used by the hypervisor, but not shared storage owned by Vdsm. If you add a new device to the volume group, you will need to edit the filter manually. """) if current_filter: print("This is the current LVM filter:") print() print(" " + lvmfilter.format_option(current_filter)) print() if advice.wwids: print("To use the recommended filter we need to add multipath") print("blacklist in /etc/multipath/conf.d/vdsm_blacklist.conf:") print() print(textwrap.indent(mpathconf.format_blacklist(advice.wwids), " ")) print() if advice.action == lvmfilter.CONFIGURE: if not args.assume_yes: if not common.confirm("Configure host? [yes,NO] "): return NEEDS_CONFIG mpathconf.configure_blacklist(advice.wwids) with lvmconf.LVMConfig() as config: config.setlist("devices", "filter", advice.filter) config.save() print("""\ Configuration completed successfully! Please reboot to verify the configuration. """) elif advice.action == lvmfilter.RECOMMEND: print("""\ WARNING: The current LVM filter does not match the recommended filter, Vdsm cannot configure the filter automatically. Please edit /etc/lvm/lvm.conf and set the 'filter' option in the 'devices' section to the recommended value. Make sure /etc/multipath/conf.d/vdsm_blacklist.conf is set with the recommended 'blacklist' section. It is recommended to reboot to verify the new configuration. """) return CANNOT_CONFIG