+++ /dev/null
-###############################################################################
-# #
-# IPFire.org - A linux based firewall #
-# Copyright (C) 2007, 2008 Michael Tremer & Christian Schmidt #
-# #
-# This program is free software: you can redistribute it and/or modify #
-# it under the terms of the GNU General Public License as published by #
-# the Free Software Foundation, either version 3 of the License, or #
-# (at your option) any later version. #
-# #
-# This program is distributed in the hope that it will be useful, #
-# but WITHOUT ANY WARRANTY; without even the implied warranty of #
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
-# GNU General Public License for more details. #
-# #
-# You should have received a copy of the GNU General Public License #
-# along with this program. If not, see <http://www.gnu.org/licenses/>. #
-# #
-###############################################################################
-
-###############################################################################
-# Definitions
-###############################################################################
-
-include $(PKGROOT)/Include
-
-PKG_NAME = pomona
-PKG_VER =
-PKG_REL = 0
-
-PKG_MAINTAINER =
-PKG_GROUP = System/Installer
-PKG_URL = http://www.ipfire.org
-PKG_LICENSE = GPLv3+
-PKG_SUMMARY = The IPFire 3.x installer.
-
-PKG_BUILD_DEPS+= pychecker
-PKG_DEPS += e2fsprogs initscripts libuser newt pakfire parted pciutils popt \
- pyfire python python-dbus python-parted python-pyblock syslog-ng udev
-
-define PKG_DESCRIPTION
- Pomona is the installer for IPFire 3.x.
-endef
-
-DIR_APP = src
-
-define STAGE_PREPARE
- cd $(DIR_APP) && make clean
- #cd $(DIR_APP) && make -C po update-po
-endef
-
-define STAGE_BUILD
- cd $(DIR_APP) && make
-endef
-
-define STAGE_TEST
- cd $(DIR_APP) && make test
-endef
-
-define STAGE_INSTALL
- cd $(DIR_APP) && make install DESTDIR=$(BUILDROOT) \
- NAME=$(NAME) SNAME=$(SNAME) VERSION=$(VERSION) KVER=$(KVER)
- cd $(DIR_APP) && make clean
-endef
+++ /dev/null
-###############################################################################
-# #
-# IPFire.org - A linux based firewall #
-# Copyright (C) 2008 Michael Tremer & Christian Schmidt #
-# #
-# This program is free software: you can redistribute it and/or modify #
-# it under the terms of the GNU General Public License as published by #
-# the Free Software Foundation, either version 3 of the License, or #
-# (at your option) any later version. #
-# #
-# This program is distributed in the hope that it will be useful, #
-# but WITHOUT ANY WARRANTY; without even the implied warranty of #
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
-# GNU General Public License for more details. #
-# #
-# You should have received a copy of the GNU General Public License #
-# along with this program. If not, see <http://www.gnu.org/licenses/>. #
-# #
-###############################################################################
-
-include Makefile.inc
-
-SUBDIRS = isys po
-
-all: subdirs
-
-install: all
- rm -rf $(PYTHONLIBDIR)
- -mkdir -p $(PYTHONLIBDIR)
- [ -d "$(PYTHONLIBDIR)" ]
- for d in $(SUBDIRS); do \
- make DESTDIR=`cd $(DESTDIR); pwd` -C $$d install; \
- [ $$? = 0 ] || exit 1; \
- done
- cp -avf *.py storage lang-table $(PYTHONLIBDIR)
- #sed -e "s/VERSION/$(VERSION)/g" \
- # -e "s/SNAME/$(SNAME)/g" \
- # -e "s/NAME/$(NAME)/g" \
- # -i $(PYTHONLIBDIR)/constants.py
- -mkdir -p $(DESTDIR)/sbin
- install -m 755 pomona $(DESTDIR)/sbin/pomona
-
-test:
- ./runpychecker.sh
-
-clean:
- rm -vf *.o *.so *.pyc *.pyo
- for d in $(SUBDIRS); do make -C $$d clean; done
-
-subdirs:
- for d in $(SUBDIRS); do make -C $$d; [ $$? = 0 ] || exit 1; done
+++ /dev/null
-###############################################################################
-# #
-# IPFire.org - A linux based firewall #
-# Copyright (C) 2008 Michael Tremer & Christian Schmidt #
-# #
-# This program is free software: you can redistribute it and/or modify #
-# it under the terms of the GNU General Public License as published by #
-# the Free Software Foundation, either version 3 of the License, or #
-# (at your option) any later version. #
-# #
-# This program is distributed in the hope that it will be useful, #
-# but WITHOUT ANY WARRANTY; without even the implied warranty of #
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
-# GNU General Public License for more details. #
-# #
-# You should have received a copy of the GNU General Public License #
-# along with this program. If not, see <http://www.gnu.org/licenses/>. #
-# #
-###############################################################################
-
-DESTDIR=$(INSTALLER_DIR)
-
-INSTALL = install -c
-INSTALL_PROGRAM = ${INSTALL}
-INSTALL_DATA = ${INSTALL} -m 644
-INSTALLNLSDIR = $(DESTDIR)/usr/share/locale
-
-PYTHONLIBDIR = $(DESTDIR)/usr/lib/pomona
-PYTHONINCLUDE= /usr/include/python2.7/
-
-CC = $(CROSS)gcc
+++ /dev/null
-#!/usr/bin/python
-
-from language import Language, LanguageWindow
-from keyboard import Keyboard, KeyboardWindow
-
-import gettext
-_ = lambda x: gettext.ldgettext("pomona", x)
-N_ = lambda x: x
-
-from constants import *
-
-class Console:
- def __init__(self, installer):
- self.installer = installer
-
- self.language = Language(installer)
- self.keyboard = Keyboard(installer)
+++ /dev/null
-#!/usr/bin/python
-
-import gettext
-_ = lambda x: gettext.ldgettext("pomona", x)
-N_ = lambda x: x
-
-PRODUCT_NAME = "IPFire"
-PROCUCT_SNAME = "ipfire"
-PRODUCT_VERSION = "3.0-prealpha2"
-PRODUCT_SLOGAN = "Gluttony"
-PRODUCT_URL = "http://www.ipfire.org/"
-
-SCREEN_ROOTLINE = _("Welcome to %s-v%s (%s)") % (PRODUCT_NAME, PRODUCT_VERSION, PRODUCT_SLOGAN,)
-SCREEN_HELPLINE = _(" <F1> for help | <Tab> between elements | <Space> selects | <F12> next screen")
-
-LOGFILE = "/tmp/installer.log"
-
-DISPATCH_FORWARD = 1
-DISPATCH_BACK = -1
-DISPATCH_NOOP = None
-
-INSTALL_OK = 0
-INSTALL_BACK = -1
-INSTALL_NOOP = -2
-
-class Translator:
- """A simple class to facilitate on-the-fly translation for newt buttons"""
- def __init__(self, button, check):
- self.button = button
- self.check = check
-
- def __getitem__(self, which):
- if which == 0:
- return _(self.button)
- elif which == 1:
- return self.check
- raise IndexError
-
- def __len__(self):
- return 2
-
-TEXT_OK_STR = N_("OK")
-TEXT_OK_CHECK = "ok"
-TEXT_OK_BUTTON = Translator(TEXT_OK_STR, TEXT_OK_CHECK)
-
-TEXT_CANCEL_STR = N_("Cancel")
-TEXT_CANCEL_CHECK = "cancel"
-TEXT_CANCEL_BUTTON = Translator(TEXT_CANCEL_STR, TEXT_CANCEL_CHECK)
-
-TEXT_BACK_STR = N_("Back")
-TEXT_BACK_CHECK = "back"
-TEXT_BACK_BUTTON = Translator(TEXT_BACK_STR, TEXT_BACK_CHECK)
-
-TEXT_YES_STR = N_("Yes")
-TEXT_YES_CHECK = "yes"
-TEXT_YES_BUTTON = Translator(TEXT_YES_STR, TEXT_YES_CHECK)
-
-TEXT_NO_STR = N_("No")
-TEXT_NO_CHECK = "no"
-TEXT_NO_BUTTON = Translator(TEXT_NO_STR, TEXT_NO_CHECK)
+++ /dev/null
-#!/usr/bin/python
-
-import console
-import storage
-#import timezone
-
-class DataStore:
- def __init__(self, installer):
- self.installer = installer
-
- self.console = console.Console(self.installer)
- self.storage = storage.Storage(self.installer)
- #self.timezone = timezone.Timezone(self.installer)
+++ /dev/null
-#!/usr/bin/python
-
-from storage import storageInitialize
-from storage.partitioning import doAutoPartition
-
-from constants import *
-from windows import *
-
-installSteps = [
- ("welcome", welcomeWindow,),
- ("experimental", experimentalWindow,),
- ("console", [ "LanguageWindow", "KeyboardWindow",]),
- ("storage", storageInitialize,),
- ("partmethod", partmethodWindow,),
- ("autopartition", autopartitionWindow,),
- #("autopartitionexecute", doAutoPartition,),
- ("partition", [ "PartitionWindow",]),
- ("bootloader", bootloaderWindow,),
- ("complete", finishedWindow,),
- ]
-
-
-class Dispatcher:
- def __init__(self, installer):
- self.installer = installer
-
- self.step = None
- self.skipSteps = {}
- self.dir = DISPATCH_FORWARD
-
- def stepIsDirect(self, step):
- """Takes a step number"""
- if len(installSteps[step]) == 2:
- return True
- else:
- return False
-
- def stepInSkipList(self, step):
- return False # XXX
-
- def nextStep(self):
- while self.step <= len(installSteps) or self.step == None:
- if self.step == None:
- self.step = 0
- else:
- self.step += self.dir
-
- if self.stepInSkipList(self.step):
- continue
- else:
- break
-
- if self.step == len(installSteps):
- return None
- else:
- return installSteps[self.step]
+++ /dev/null
-#!/usr/bin/python
-
-import os
-import signal
-import string
-import sys
-import traceback
-import types
-
-from cPickle import Pickler
-
-dumpHash = {}
-
-def dumpClass(instance, fd, level=0, parentkey=""):
- # protect from loops
- try:
- if not dumpHash.has_key(instance):
- dumpHash[instance] = None
- else:
- fd.write("Already dumped\n")
- return
- except TypeError:
- fd.write("Cannot dump object\n")
- return
-
- if (instance.__class__.__dict__.has_key("__str__") or
- instance.__class__.__dict__.has_key("__repr__")):
- fd.write("%s\n" % (instance,))
- return
-
- fd.write("%s instance, containing members:\n" % (instance.__class__.__name__))
- pad = ' ' * ((level) * 2)
-
- for key, value in instance.__dict__.items():
- if parentkey != "":
- curkey = parentkey + "." + key
- else:
- curkey = key
-
- if type(value) == types.ListType:
- fd.write("%s%s: [" % (pad, curkey))
- first = 1
- for item in value:
- if not first:
- fd.write(", ")
- else:
- first = 0
- if type(item) == types.InstanceType:
- dumpClass(item, fd, level + 1,)
- else:
- fd.write("%s" % (item,))
- fd.write("]\n")
-
- elif type(value) == types.DictType:
- fd.write("%s%s: {" % (pad, curkey))
- first = 1
- for k, v in value.items():
- if not first:
- fd.write(", ")
- else:
- first = 0
- if type(k) == types.StringType:
- fd.write("'%s': " % (k,))
- else:
- fd.write("%s: " % (k,))
- if type(v) == types.InstanceType:
- dumpClass(v, fd, level + 1, parentkey = curkey)
- else:
- fd.write("%s" % (v,))
- fd.write("}\n")
-
- elif type(value) == types.InstanceType:
- fd.write("%s%s: " % (pad, curkey))
- dumpClass(value, fd, level + 1, parentkey=curkey)
-
- else:
- fd.write("%s%s: %s\n" % (pad, curkey, value))
-
-def dumpException(out, text, tb, installer):
- p = Pickler(out)
-
- out.write(text)
-
- trace = tb
- if trace is not None:
- while trace.tb_next:
- trace = trace.tb_next
- frame = trace.tb_frame
- out.write("\nLocal variables in innermost frame:\n")
- try:
- for (key, value) in frame.f_locals.items():
- out.write("%s: %s\n" % (key, value))
- except:
- pass
-
- try:
- out.write("\n\n")
- dumpClass(installer, out)
- except:
- out.write("\nException occurred during state dump:\n")
- traceback.print_exc(None, out)
-
- for file in ("/root/syslog", "/root/pomona.log", "/root/install.log"):
- try:
- f = open(file, 'r')
- line = "\n\n%s:\n" % (file,)
- while line:
- out.write(line)
- line = f.readline()
- f.close()
- except IOError:
- pass
- except:
- out.write("\nException occurred during %s file copy:\n" % (file,))
- traceback.print_exc(None, out)
-
-# Reverse the order that tracebacks are printed so people will hopefully quit
-# giving us the least useful part of the exception in bug reports.
-def formatException(type, value, tb):
- lst = traceback.format_tb(tb)
- lst.reverse()
- lst.insert(0, 'Traceback (most recent call first):\n')
- lst.extend(traceback.format_exception_only(type, value))
- return lst
-
-def handleException(installer, (type, value, tb)):
- # restore original exception handler
- sys.excepthook = sys.__excepthook__
-
- installer.log.error("Exception occured. Read more in /tmp/instdump.txt.")
-
- # get traceback information
- list = formatException(type, value, tb)
- text = string.joinfields(list, "")
-
- # save to local storage
- out = open("/tmp/instdump.txt", "w")
- dumpException(out, text, tb, installer)
- out.close()
-
- win = installer.intf.exceptionWindow(text, "/tmp/instdump.txt")
- if not win:
- installer.intf.__del__()
- os.kill(os.getpid(), signal.SIGKILL)
-
- while 1:
- win.run()
-
- if win.getrc() == 0:
- installer.intf.__del__()
- os.kill(os.getpid(), signal.SIGKILL)
+++ /dev/null
-###############################################################################
-# #
-# IPFire.org - A linux based firewall #
-# Copyright (C) 2008 Michael Tremer & Christian Schmidt #
-# #
-# This program is free software: you can redistribute it and/or modify #
-# it under the terms of the GNU General Public License as published by #
-# the Free Software Foundation, either version 3 of the License, or #
-# (at your option) any later version. #
-# #
-# This program is distributed in the hope that it will be useful, #
-# but WITHOUT ANY WARRANTY; without even the implied warranty of #
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
-# GNU General Public License for more details. #
-# #
-# You should have received a copy of the GNU General Public License #
-# along with this program. If not, see <http://www.gnu.org/licenses/>. #
-# #
-###############################################################################
-
-include ../Makefile.inc
-
-OBJECTS = isys.o mount.o
-
-CFLAGS += -I$(PYTHONINCLUDE)
-LDFLAGS =
-LIBS =
-
-all: depend _isys.so
-
-depend: $(patsubst %.o,%.c,$(OBJECTS))
- $(CPP) -M $(CFLAGS) $(patsubst %.o,%.c,$(OBJECTS)) > depend
-
-%.o: %.c
- $(CC) -c $(CFLAGS) -o $@ $<
-
-_isys.so: $(OBJECTS)
- $(CC) -shared $(CFLAGS) $(LDFLAGS) $(LIBS) -o $@ $(OBJECTS)
-
-install: _isys.so isys.py
- cp -vf _isys.so isys.py $(PYTHONLIBDIR)
-
-clean:
- rm -vf $(OBJECTS) depend _isys.so *.py[co]
-
-test: _isys.so
- python -c "import isys"
-
-ifeq (depend,$(wildcard depend))
-include depend
-endif
+++ /dev/null
-
-
-#include <Python.h>
-
-#include "isys.h"
-#include "mount.h"
-
-
-static PyObject * doMount(PyObject * s, PyObject * args);
-static PyObject * doUMount(PyObject * s, PyObject * args);
-
-static PyMethodDef isysModuleMethods[] = {
- { "mount", (PyCFunction) doMount, METH_VARARGS, NULL },
- { "umount", (PyCFunction) doUMount, METH_VARARGS, NULL },
-};
-
-void init_isys(void) {
- PyObject * m, * d;
-
- m = Py_InitModule("_isys", isysModuleMethods);
- d = PyModule_GetDict(m);
-}
-
-static PyObject * doMount(PyObject * s, PyObject * args) {
- char *err = NULL, *fs, *device, *mntpoint, *flags = NULL;
- int rc;
-
- if (!PyArg_ParseTuple(args, "sss|z", &fs, &device, &mntpoint,
- &flags)) return NULL;
-
- rc = doPwMount(device, mntpoint, fs, flags, &err);
- if (rc == MOUNT_ERR_ERRNO)
- PyErr_SetFromErrno(PyExc_SystemError);
- else if (rc) {
- PyObject *tuple = PyTuple_New(2);
-
- PyTuple_SetItem(tuple, 0, PyInt_FromLong(rc));
- PyTuple_SetItem(tuple, 1, PyString_FromString(err));
- PyErr_SetObject(PyExc_SystemError, tuple);
- }
-
- if (rc)
- return NULL;
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject * doUMount(PyObject * s, PyObject * args) {
- char * fs;
-
- if (!PyArg_ParseTuple(args, "s", &fs))
- return NULL;
-
- if (umount(fs)) {
- PyErr_SetFromErrno(PyExc_SystemError);
- return NULL;
- }
-
- Py_INCREF(Py_None);
- return Py_None;
-}
+++ /dev/null
-#ifndef H_ISYS
-#define H_ISYS
-
-
-#endif
+++ /dev/null
-#!/usr/bin/python
-
-import _isys
-
-import os
-import string
-
-mountCount = {}
-
-## Mount a filesystem, similar to the mount system call.
-# @param device The device to mount. If bindMount is 1, this should be an
-# already mounted directory. Otherwise, it should be a device
-# name.
-# @param location The path to mount device on.
-# @param fstype The filesystem type on device. This can be disk filesystems
-# such as vfat or ext3, or pseudo filesystems such as proc or
-# selinuxfs.
-# @param readOnly Should this filesystem be mounted readonly?
-# @param bindMount Is this a bind mount? (see the mount(8) man page)
-# @param remount Are we mounting an already mounted filesystem?
-# @return The return value from the mount system call.
-def mount(device, location, fstype = "ext2", readOnly = 0, bindMount = 0, remount = 0, options = "defaults"):
- flags = None
- location = os.path.normpath(location)
- opts = string.split(options)
-
- # We don't need to create device nodes for devices that start with '/'
- # (like '/usbdevfs') and also some special fake devices like 'proc'.
- # First try to make a device node and if that fails, assume we can
- # mount without making a device node. If that still fails, the caller
- # will have to deal with the exception.
- # We note whether or not we created a node so we can clean up later.
-
- if mountCount.has_key(location) and mountCount[location] > 0:
- mountCount[location] = mountCount[location] + 1
- return
-
- if readOnly or bindMount or remount:
- if readOnly:
- opts.append("ro")
- if bindMount:
- opts.append("bind")
- if remount:
- opts.append("remount")
-
- flags = ",".join(opts)
-
- #log.debug("isys.py:mount()- going to mount %s on %s with options %s" %(device, location, flags))
- rc = _isys.mount(fstype, device, location, flags)
-
- if not rc:
- mountCount[location] = 1
-
- return rc
-
-## Unmount a filesystem, similar to the umount system call.
-# @param what The directory to be unmounted. This does not need to be the
-# absolute path.
-# @param removeDir Should the mount point be removed after being unmounted?
-# @return The return value from the umount system call.
-def umount(what, removeDir = 1):
- what = os.path.normpath(what)
-
- if not os.path.isdir(what):
- raise ValueError, "isys.umount() can only umount by mount point"
-
- if mountCount.has_key(what) and mountCount[what] > 1:
- mountCount[what] = mountCount[what] - 1
- return
-
- rc = _isys.umount(what)
-
- if removeDir and os.path.isdir(what):
- os.rmdir(what)
-
- if not rc and mountCount.has_key(what):
- del mountCount[what]
-
- return rc
+++ /dev/null
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "mount.h"
-
-static int mkdirIfNone(char * directory);
-
-static int readFD(int fd, char **buf) {
- char *p;
- size_t size = 4096;
- int s, filesize = 0;
-
- *buf = calloc(4096, sizeof (char));
- if (*buf == NULL)
- abort();
-
- do {
- p = &(*buf)[filesize];
- s = read(fd, p, 4096);
- if (s < 0)
- break;
-
- filesize += s;
- if (s == 0)
- break;
-
- size += s;
- *buf = realloc(*buf, size);
- if (*buf == NULL)
- abort();
- } while (1);
-
- if (filesize == 0 && s < 0) {
- free(*buf);
- *buf = NULL;
- return -1;
- }
-
- return filesize;
-}
-
-int doPwMount(char *dev, char *where, char *fs, char *options, char **err) {
- int rc, child, status, pipefd[2];
- char *opts = NULL, *device;
-
- if (mkdirChain(where))
- return MOUNT_ERR_ERRNO;
-
- if (strstr(fs, "nfs")) {
- if (options) {
- if (asprintf(&opts, "%s,nolock", options) == -1) {
- fprintf(stderr, "%s: %d: %s\n", __func__, __LINE__,
- strerror(errno));
- fflush(stderr);
- abort();
- }
- } else {
- opts = strdup("nolock");
- }
- device = strdup(dev);
- } else {
- if ((options && strstr(options, "bind") == NULL) &&
- strncmp(dev, "LABEL=", 6) && strncmp(dev, "UUID=", 5) &&
- *dev != '/') {
- if (asprintf(&device, "/dev/%s", dev) == -1) {
- fprintf(stderr, "%s: %d: %s\n", __func__, __LINE__,
- strerror(errno));
- fflush(stderr);
- abort();
- }
- } else {
- device = strdup(dev);
- }
- if (options)
- opts = strdup(options);
- }
-
- if (pipe(pipefd))
- return MOUNT_ERR_ERRNO;
-
- if (!(child = fork())) {
- int fd;
-
- close(pipefd[0]);
-
- /* Close stdin entirely, redirect stdout to tty5, and redirect stderr
- * to a pipe so we can put error messages into exceptions. We'll
- * only use these messages should mount also return an error code.
- */
- fd = open("/dev/tty5", O_RDONLY);
- close(STDIN_FILENO);
- dup2(fd, STDIN_FILENO);
- close(fd);
-
- fd = open("/dev/tty5", O_WRONLY);
- close(STDOUT_FILENO);
- dup2(fd, STDOUT_FILENO);
-
- dup2(pipefd[1], STDERR_FILENO);
-
- if (opts) {
- rc = execl("/bin/mount",
- "/bin/mount", "-n", "-t", fs, "-o", opts, device, where, NULL);
- exit(1);
- }
- else {
- rc = execl("/bin/mount", "/bin/mount", "-n", "-t", fs, device, where, NULL);
- exit(1);
- }
- }
-
- close(pipefd[1]);
-
- if (err != NULL)
- rc = readFD(pipefd[0], err);
-
- close(pipefd[0]);
- waitpid(child, &status, 0);
-
- free(opts);
- free(device);
- if (!WIFEXITED(status) || (WIFEXITED(status) && WEXITSTATUS(status)))
- return MOUNT_ERR_OTHER;
-
- return 0;
-}
-
-int mkdirChain(char * origChain) {
- char * chain;
- char * chptr;
-
- chain = alloca(strlen(origChain) + 1);
- strcpy(chain, origChain);
- chptr = chain;
-
- while ((chptr = strchr(chptr, '/'))) {
- *chptr = '\0';
- if (mkdirIfNone(chain)) {
- *chptr = '/';
- return MOUNT_ERR_ERRNO;
- }
-
- *chptr = '/';
- chptr++;
- }
-
- if (mkdirIfNone(chain))
- return MOUNT_ERR_ERRNO;
-
- return 0;
-}
-
-static int mkdirIfNone(char * directory) {
- int rc, mkerr;
- char * chptr;
-
- /* If the file exists it *better* be a directory -- I'm not going to
- actually check or anything */
- if (!access(directory, X_OK))
- return 0;
-
- /* if the path is '/' we get ENOFILE not found" from mkdir, rather
- then EEXIST which is weird */
- for (chptr = directory; *chptr; chptr++)
- if (*chptr != '/')
- break;
- if (!*chptr)
- return 0;
-
- rc = mkdir(directory, 0755);
- mkerr = errno;
-
- if (!rc || mkerr == EEXIST)
- return 0;
-
- return MOUNT_ERR_ERRNO;
-}
+++ /dev/null
-
-#ifndef H_MOUNT
-#define H_MOUNT
-
-#define MOUNT_ERR_ERRNO 1
-#define MOUNT_ERR_OTHER 2
-
-#include <sys/mount.h> /* for umount() */
-
-int doPwMount(char *dev, char *where, char *fs, char *options, char **err);
-int mkdirChain(char * origChain);
-
-#endif
+++ /dev/null
-#!/usr/bin/python
-
-import os
-
-from snack import ListboxChoiceWindow
-
-import gettext
-_ = lambda x: gettext.ldgettext("pomona", x)
-
-from constants import *
-
-def gkn(str):
- idx = str.find("|")
- if idx == -1:
- return str
- return str[idx + 1:]
-
-class KeyboardModels:
- def __init__(self):
- self._modelDict = {
- 'ar-azerty' : [N_('keyboard|Arabic (azerty)'), 'us,ara', 'pc105', 'azerty', 'grp:shifts_toggle,grp_led:scroll'],
- 'ar-azerty-digits' : [N_('keyboard|Arabic (azerty/digits)'), 'us,ara', 'pc105', 'azerty_digits', 'grp:shifts_toggle,grp_led:scroll'],
- 'ar-digits' : [N_('keyboard|Arabic (digits)'), 'us,ara', 'pc105', 'digits', 'grp:shifts_toggle,grp_led:scroll'],
- 'ar-qwerty' : [N_('keyboard|Arabic (qwerty)'), 'us,ara', 'pc105', 'qwerty', 'grp:shifts_toggle,grp_led:scroll'],
- 'ar-qwerty-digits' : [N_('keyboard|Arabic (qwerty/digits)'), 'us,ara', 'pc105', 'qwerty_digits', 'grp:shifts_toggle,grp_led:scroll'],
- 'be-latin1' : [N_('keyboard|Belgian (be-latin1)'), 'be', 'pc105', '', ''],
- 'ben' : [N_('keyboard|Bengali (Inscript)'), 'us,in', 'pc105', 'ben', 'grp:shifts_toggle,grp_led:scroll'],
- 'ben-probhat' : [N_('keyboard|Bengali (Probhat)'), 'us,in', 'pc105', 'ben_probhat', 'grp:shifts_toggle,grp_led:scroll'],
- 'bg_bds-utf8' : [N_('keyboard|Bulgarian'), 'us,bg', 'pc105', '', 'grp:shifts_toggle,grp_led:scroll'],
- 'bg_pho-utf8' : [N_('keyboard|Bulgarian (Phonetic)'), 'us,bg', 'pc105', ',phonetic', 'grp:shifts_toggle,grp_led:scroll'],
- 'br-abnt2' : [N_('keyboard|Brazilian (ABNT2)'), 'br', 'abnt2', '', ''],
- 'cf' : [N_('keyboard|French Canadian'), 'ca(fr)', 'pc105', '', ''],
- 'croat' : [N_('keyboard|Croatian'), 'hr', 'pc105', '', '' ],
- 'cz-us-qwertz' : [N_('keyboard|Czech'), 'us,cz', 'pc105', '', 'grp:shifts_toggle,grp_led:scroll'],
- 'cz-lat2' : [N_('keyboard|Czech (qwerty)'), 'cz', 'pc105', 'qwerty', ''],
- 'de' : [N_('keyboard|German'), 'de', 'pc105', '', ''],
- 'de-latin1' : [N_('keyboard|German (latin1)'), 'de', 'pc105', '', ''],
- 'de-latin1-nodeadkeys' : [N_('keyboard|German (latin1 w/ no deadkeys)'), 'de', 'pc105', 'nodeadkeys', ''],
- 'dev' : [N_('keyboard|Devanagari (Inscript)'), 'us,dev', 'pc105', '', 'grp:shifts_toggle,grp_led:scroll'],
- 'dvorak' : [N_('keyboard|Dvorak'), 'us', 'pc105', 'dvorak', ''],
- 'dk' : [N_('keyboard|Danish'), 'dk', 'pc105', '', ''],
- 'dk-latin1' : [N_('keyboard|Danish (latin1)'), 'dk', 'pc105', '', ''],
- 'es' : [N_('keyboard|Spanish'), 'es', 'pc105', '', ''],
- 'et' : [N_('keyboard|Estonian'), 'ee', 'pc105', '', ''],
- 'fi' : [N_('keyboard|Finnish'), 'fi', 'pc105', '', ''],
- 'fi-latin1' : [N_('keyboard|Finnish (latin1)'), 'fi', 'pc105', '', ''],
- 'fr' : [N_('keyboard|French'), 'fr', 'pc105', '', ''],
- 'fr-latin9' : [N_('keyboard|French (latin9)'), 'fr', 'pc105', 'latin9', ''],
- 'fr-latin1' : [N_('keyboard|French (latin1)'), 'fr', 'pc105', '', ''],
- 'fr-pc' : [N_('keyboard|French (pc)'), 'fr', 'pc105', '', ''],
- 'fr_CH' : [N_('keyboard|Swiss French'), 'fr_CH', 'pc105', '', ''],
- 'fr_CH-latin1' : [N_('keyboard|Swiss French (latin1)'), 'ch', 'pc105', 'fr', ''],
- 'gr' : [N_('keyboard|Greek'), 'us,gr', 'pc105', '', 'grp:shifts_toggle,grp_led:scroll'],
- 'guj' : [N_('keyboard|Gujarati (Inscript)'), 'us,in', 'pc105', 'guj', 'grp:shifts_toggle,grp_led:scroll'],
- 'gur' : [N_('keyboard|Punjabi (Inscript)'), 'us,gur', 'pc105', '', 'grp:shifts_toggle,grp_led:scroll'],
- 'hu' : [N_('keyboard|Hungarian'), 'hu', 'pc105', '', ''],
- 'hu101' : [N_('keyboard|Hungarian (101 key)'), 'hu', 'pc105', 'qwerty', ''],
- 'is-latin1' : [N_('keyboard|Icelandic'), 'is', 'pc105', '', ''],
- 'it' : [N_('keyboard|Italian'), 'it', 'pc105', '', ''],
- 'it-ibm' : [N_('keyboard|Italian (IBM)'), 'it', 'pc105', '', ''],
- 'it2' : [N_('keyboard|Italian (it2)'), 'it', 'pc105', '', ''],
- 'jp106' : [N_('keyboard|Japanese'), 'jp', 'jp106', '', ''],
- 'ko' : [N_('keyboard|Korean'), 'kr', 'pc105', '', ''],
- 'la-latin1' : [N_('keyboard|Latin American'), 'latam', 'pc105', '', ''],
- 'mk-utf' : [N_('keyboard|Macedonian'), 'us,mkd', 'pc105', '','grp:shifts_toggle,grp_led:scroll'],
- 'nl' : [N_('keyboard|Dutch'), 'nl', 'pc105', '', ''],
- 'no' : [N_('keyboard|Norwegian'), 'no', 'pc105', '', ''],
- 'pl2' : [N_('keyboard|Polish'), 'pl', 'pc105', '', ''],
- 'pt-latin1' : [N_('keyboard|Portuguese'), 'pt', 'pc105', '', ''],
- 'ro_win' : [N_('keyboard|Romanian'), 'ro', 'pc105', '', ''],
- 'ru' : [N_('keyboard|Russian'), 'us,ru', 'pc105', '', 'grp:shifts_toggle,grp_led:scroll'],
- 'sr-cy' : [N_('keyboard|Serbian'), 'cs', 'pc105', '', ''],
- 'sr-latin' : [N_('keyboard|Serbian (latin)'), 'cs', 'pc105', 'latin', ''],
- 'sv-latin1' : [N_('keyboard|Swedish'), 'se', 'pc105', '', ''],
- 'sg' : [N_('keyboard|Swiss German'), 'ch', 'pc105', 'de_nodeadkeys', ''],
- 'sg-latin1' : [N_('keyboard|Swiss German (latin1)'), 'ch', 'pc105', 'de_nodeadkeys', ''],
- 'sk-qwerty' : [N_('keyboard|Slovak (qwerty)'), 'sk', 'pc105', '', 'qwerty'],
- 'slovene' : [N_('keyboard|Slovenian'), 'si', 'pc105', '', ''],
- 'tml-inscript' : [N_('keyboard|Tamil (Inscript)'), 'us,in', 'pc105', 'tam', 'grp:shifts_toggle,grp_led:scroll'],
- 'tml-uni' : [N_('keyboard|Tamil (Typewriter)'), 'us,in', 'pc105', 'tam_TAB', 'grp:shifts_toggle,grp_led:scroll'],
- 'trq' : [N_('keyboard|Turkish'), 'tr', 'pc105', '', ''],
- 'uk' : [N_('keyboard|United Kingdom'), 'gb', 'pc105', '', ''],
- 'ua-utf' : [N_('keyboard|Ukrainian'), 'us,ua', 'pc105', '', 'grp:shifts_toggle,grp_led:scroll'],
- 'us-acentos' : [N_('keyboard|U.S. International'), 'us', 'pc105', 'intl', ''],
- 'us' : [N_('keyboard|U.S. English'), 'us+inet', 'pc105', '', ''],
- }
-
- def getAllModels(self):
- ret = []
- for model in self._modelDict.values():
- ret.append(gkn(_(model[0])))
- return ret
-
-class Keyboard:
- def __init__(self, installer):
- self.installer = installer
-
- self.models = KeyboardModels()
-
- def getKeymap(self):
- return gkn(self.models._modelDict["us"][0]) # XXX
-
- def setKeymap(self, keymap):
- self.installer.log.debug("Set keymap to \"%s\"" % keymap)
-
-
-class KeyboardWindow:
- def __call__(self, installer):
- #if flags.virtpconsole:
- # return INSTALL_NOOP
-
- keyboard = installer.ds.console.keyboard
-
- keyboards = keyboard.models.getAllModels()
- keyboards.sort()
-
- default = keyboard.getKeymap()
-
- (button, choice) = ListboxChoiceWindow(installer.intf.screen,
- _("Keyboard Selection"),
- _("Which model keyboard is attached to this computer?"),
- keyboards, buttons = [TEXT_OK_BUTTON, TEXT_BACK_BUTTON],
- width = 30, scroll = 1, height = 8, default = default)
-
- if button == TEXT_BACK_CHECK:
- return INSTALL_BACK
-
- keyboard.setKeymap(keyboards[choice])
- #keyboard.activate()
-
- return INSTALL_OK
+++ /dev/null
-English en LatArCyrHeb-16 en_US.UTF-8 us America/New_York
-German de LatArCyrHeb-16 de_DE.UTF-8 de-latin1-nodeadkeys Europe/Berlin
-Danish da LatArCyrHeb-16 da_DK.UTF-8 dk Europe/Copenhagen
+++ /dev/null
-#/usr/bin/python
-
-import os
-import locale
-import string
-
-from snack import ListboxChoiceWindow
-
-import gettext
-_ = lambda x: gettext.ldgettext("pomona", x)
-
-from constants import *
-
-# Converts a single language into a "language search path". For example,
-# de_DE.utf8@euro would become "de_DE.utf8@euro de_DE.utf8 de_DE de"
-def expandLangs(astring):
- langs = [astring]
- charset = None
- # remove charset ...
- if '.' in astring:
- langs.append(string.split(astring, '.')[0])
-
- if '@' in astring:
- charset = string.split(astring, '@')[1]
-
- # also add 2 character language code ...
- if len(astring) > 2:
- if charset:
- langs.append("%s@%s" %(astring[:2], charset))
-
- langs.append(astring[:2])
-
- return langs
-
-class Language:
- def __init__(self, installer):
- self.installer = installer
-
- self.languages = {}
-
- # nick -> (name, short name, font, keyboard, timezone) mapping
- search = ('lang-table', '../lang-table', '/usr/lib/pomona/lang-table', '/etc/lang-table')
- for path in search:
- if os.access(path, os.R_OK):
- f = open(path, "r")
- break
-
- for line in f.readlines():
- line = line.strip() #string.strip(line)
- l = line.split("\t") #.split(line, '\t')
-
- # throw out invalid lines
- if len(l) < 6:
- continue
-
- (name, short, font, locale, keyboard, timezone) = l
- self.languages[short] = (name, _(name), font, locale, timezone)
-
- f.close()
-
- def getAllLanguages(self):
- ret = []
- for (name, name2, font, locale, timezone) in self.languages.values():
- ret.append(name2)
- return ret
-
- def getLanguage(self):
- return "English" # XXX
-
- def setLanguage(self, lang):
- self.installer.log.debug("Set language to \"%s\"" % lang)
- os.environ["LC_NUMERIC"] = 'C'
- #XXX os.environ["LANG"] = "de_DE.utf8"
-
- try:
- locale.setlocale(locale.LC_ALL, "")
- except locale.Error:
- pass
-
-
-class LanguageWindow:
- def __call__(self, installer):
- language = installer.ds.console.language
-
- languages = language.getAllLanguages()
- languages.sort()
-
- current = language.getLanguage()
-
- (button, choice) = ListboxChoiceWindow(installer.intf.screen,
- _("Language Selection"),
- _("What language would you like to use during the "
- "installation process?"), languages,
- buttons = [TEXT_OK_BUTTON, TEXT_BACK_BUTTON],
- width = 30, default = _(current), scroll = 1,
- height = min((8, len(languages))))
-
- if button == TEXT_BACK_CHECK:
- return INSTALL_BACK
-
- language.setLanguage(languages[choice])
- #installer.ds.timezone.setTimezoneInfo(id.console.getDefaultTimeZone())
-
- return INSTALL_OK
-
-
-if __name__ == "__main__":
- language = Language(None)
- print language.getAllLanguages()
+++ /dev/null
-#!/usr/bin/python
-
-import time
-
-from constants import *
-
-class Logger:
- def __init__(self):
- self.logfile = open(LOGFILE, "w+")
-
- self.logline = "%s %8s: %s\n" # time, group, message
-
- def critical(self, msg):
- self.logfile.write(self.logline % (self.time(), "CRITICAL", msg,))
- self.flush()
-
- def info(self, msg):
- self.logfile.write(self.logline % (self.time(), "INFO", msg,))
- self.flush()
-
- def debug(self, msg):
- self.logfile.write(self.logline % (self.time(), "DEBUG", msg,))
- self.flush()
-
- def error(self, msg):
- self.logfile.write(self.logline % (self.time(), "ERROR", msg,))
- self.flush()
-
- def warning(self, msg):
- self.logfile.write(self.logline % (self.time(), "WARNING", msg,))
- self.flush()
-
- def stdout(self, msg):
- self.logfile.write(self.logline % (self.time(), "STDOUT", msg,))
- self.flush()
- print msg
-
- def time(self):
- return time.strftime("%d %b %Y %H:%M:%S")
-
- def __del__(self):
- self.logfile.close()
-
- def flush(self):
- self.logfile.flush()
+++ /dev/null
-#!/usr/bin/python
-
-from snack import *
-
-from storage.deviceaction import *
-import storage
-import storage.formats as formats
-from storage.devicelibs.lvm import safeLvmName
-
-from constants import *
-
-import gettext
-_ = lambda x: gettext.ldgettext("pomona", x)
-
-def logicalVolumeGroupList(installer):
- storage = installer.ds.storage
-
- vgs = []
- for vg in storage.vgs:
- vgs.append(vg.name)
- (button, choice) = ListboxChoiceWindow(installer.intf.screen,
- _("Volume Group Selection"),
- _("What language would you like to use during the "
- "installation process?"), vgs,
- buttons = [TEXT_OK_BUTTON, TEXT_BACK_BUTTON],
- width = 30, scroll = 1,
- height = min((8, len(vgs))))
- if button == TEXT_BACK_CHECK:
- return
-
- for vg in storage.vgs:
- if choice == vg.name:
- return vg
- return
-
-class PartitionWindow(object):
- def populate(self):
- self.lb.clear()
-
- for vg in self.storage.vgs:
- self.lb.append([vg.name, "", "", "",], vg)
-
- freespace = vg.freeSpace
- if freespace:
- self.lb.append([" %s" % _("Free Space"), "", "", "%dM" % freespace,],
- None, [LEFT, LEFT, LEFT, RIGHT])
-
- for disk in self.storage.disks:
- self.lb.append([disk.path, "", "", "",], None)
- for part in self.storage.partitions:
- if disk == part.disk:
- mountpoint = type = ""
- if part.format:
- type = part.format.name
- try:
- if part.format.mountpoint:
- mountpoint = part.format.mountpoint
- except AttributeError:
- pass
- self.lb.append([" %s" % part.name,
- mountpoint,
- type,
- "%dM" % part.size,],
- part,
- [LEFT, LEFT, LEFT, RIGHT])
-
- def makeFileSystemList(self, device):
- grid = Grid(1, 2)
-
- label = Label(_("File System type:"))
- grid.setField(label, 0, 0)
-
- fstype = Listbox(height=4, scroll=1)
- for fs in sorted(formats.device_formats.values()):
- if not fs.supported:
- continue
- if fs.formattable:
- fstype.append(fs._type, fs)
- # XXX select default
- #current = formats.device_formats[formats.get_default_filesystem_type()]
- #print current
- #fstype.setCurrent(current)
- ### XXX Callback
- grid.setField(fstype, 0, 1)
- return (grid, fstype)
-
- def makeDriveList(self, device):
- grid = Grid(1, 2)
-
- label = Label(_("Allowable Drives:"))
- grid.setField(label, 0, 0)
-
- drivelist = CheckboxTree(height=4, scroll=1)
- for disk in self.storage.disks:
- drivelist.append(disk.name)
- grid.setField(drivelist, 0, 1)
- return (grid, drivelist)
-
- def makeMountPoint(self, device):
- grid = Grid(2, 1)
- label = Label(_("Mount Point:"))
- grid.setField(label, 0, 0, (0,0,0,0), anchorLeft = 1)
-
- try:
- mountpoint = device.format.mountpoint
- except AttributeError:
- mountpoint = ""
- mount = Entry(20, mountpoint)
-
- grid.setField(mount, 1, 0, anchorRight = 1, growx = 1)
-
- return (grid, mount)
-
- def makeVGName(self, device):
- grid = Grid(2, 1)
- label = Label(_("VG Name:"))
- grid.setField(label, 0, 0, (0,0,0,0), anchorLeft = 1)
- name = Entry(20, device.name)
- grid.setField(name, 1, 0, anchorRight = 1, growx = 1)
- return (grid, name)
-
- def newCb(self):
- choices = [_("Partition"), _("RAID"), _("Logical Volume Group")]
-
- if self.storage.vgs:
- choices.append(_("Logical Volume Device"))
-
- (button, choice) = ListboxChoiceWindow(self.installer.intf.screen,
- _("New device"),
- _("Which type of device do you want to create?\n\n"),
- choices, buttons = [TEXT_OK_BUTTON, TEXT_BACK_BUTTON],
- width = 35, height = len(choices))
-
- if button == TEXT_BACK_CHECK:
- return
-
- choice = choices[choice]
- if choice == _("Partition"):
- self.newPart()
- elif choice == _("RAID"):
- pass # XXX self.newRaid()
- elif choice == _("Logical Volume Group"):
- self.newVG()
- elif choice == _("Logical Volume Device"):
- self.newLV()
-
- def newPart(self):
- disks = []
- for disk in self.storage.disks:
- disks.append(("%s - %s" % (disk.name, disk.model,), disk,))
-
- (button, disk) = ListboxChoiceWindow(self.installer.intf.screen,
- _("Disk Selection"),
- _("Choose the disk you want create the new "
- "partition on."),
- disks, buttons = [TEXT_OK_BUTTON, TEXT_CANCEL_BUTTON],
- height=len(disks))
- if button == TEXT_CANCEL_CHECK:
- return
-
- device = self.storage.newPartition(parents=disk)
- self.editPart(device=device)
-
- def newVG(self):
- device = self.storage.newVG()
- self.storage.createDevice(device)
- self.editVG(device=device)
-
- def newLV(self):
- vg = logicalVolumeGroupList(self.installer)
- if vg:
- device = self.storage.newLV(vg=vg)
- self.editLV(device=device)
-
- def editPart(self, device):
- if not device:
- return
-
- row = 0
- actions = []
-
- if not device.exists:
- tstr = _("Add Partition")
- else:
- tstr = _("Edit Partition")
- grid = GridForm(self.screen, tstr, 1, 6)
-
- if device.exists:
- if device.format.exists and getattr(device.format, "label", None):
- lbl = Label("%s %s" % (_("Original File System Label:"), device.format.label))
- grid.add(lbl, 0, row)
- row += 1
-
- (mountgrid, mountpoint) = self.makeMountPoint(device)
- grid.add(mountgrid, 0, row)
- row += 1
-
- if not device.exists:
- subgrid1 = Grid(2, 1)
-
- (fsgrid, fstype) = self.makeFileSystemList(device)
- subgrid1.setField(fsgrid, 0, 0)
-
- #(devgrid, drivelist) = self.makeDriveList(device)
- #subgrid1.setField(devgrid, 0, 0)
-
- #(fsgrid, fstype) = self.makeFileSystemList(device)
- #subgrid1.setField(fsgrid, 1, 0, (1,0,0,0), growx=1)
-
- grid.add(subgrid1, 0, row, (0,1,0,0), growx=1)
- row += 1
- else:
- pass
-
- bb = ButtonBar(self.screen, (TEXT_OK_BUTTON, TEXT_CANCEL_BUTTON))
- grid.add(bb, 0, row, (0,1,0,0), growx = 1)
- row += 1
-
- while 1:
- rc = grid.run()
- button = bb.buttonPressed(rc)
-
- if button == TEXT_CANCEL_CHECK:
- break
-
- if mountpoint.value() and not mountpoint.value().startswith("/"):
- self.installer.intf.messageWindow(_("Error"),
- _("Mountpoint must be an absolute path."))
- continue
-
- if device.format:
- device.format.mountpoint = mountpoint.value()
-
- if not device.exists:
- actions.append(ActionCreateDevice(self.installer, device))
-
- break
-
- self.screen.popWindow()
- return actions
-
- def editVG(self, device):
- if not device.exists:
- tstr = _("Add Logical Volume Group")
- else:
- tstr = _("Edit Logical Volume Group")
- grid = GridForm(self.screen, tstr, 1, 6)
- row = 0
-
- (namegrid, name) = self.makeVGName(device)
- grid.add(namegrid, 0, row)
- row += 1
-
- # XXX size?
-
- bb = ButtonBar(self.screen, (TEXT_OK_BUTTON, TEXT_CANCEL_BUTTON))
- grid.add(bb, 0, row, (0,1,0,0), growx = 1)
- row += 1
-
- while 1:
- rc = grid.run()
- button = bb.buttonPressed(rc)
-
- if button == TEXT_CANCEL_CHECK:
- break
-
- if not name.value():
- self.installer.intf.messageWindow(_("Error"),
- _("You must enter a name for the "
- "Logical Volume Group."))
- continue
- device.name = safeLvmName(name.value())
-
- break
-
- self.screen.popWindow()
-
- editLV = editPart
-
- def editCb(self):
- device = self.lb.current()
- if not device:
- self.installer.intf.messageWindow(_("Unable To Edit"),
- _("You must first select a partition to edit."))
- return
-
- reason = self.storage.deviceImmutable(device)
- if reason:
- self.installer.intf.messageWindow(_("Unable To Edit"),
- _("You cannot edit this device:\n\n%s")
- % reason,)
- return
-
- actions = None
- if device.type == "mdarray":
- pass #self.editRaidArray(device)
- elif device.type == "lvmvg":
- actions = self.editVG(device)
- elif device.type == "lvmlv":
- actions = self.editLV(device)
- elif isinstance(device, storage.devices.PartitionDevice):
- actions = self.editPart(device)
-
- for action in actions:
- self.storage.devicetree.registerAction(action)
-
- def deleteCb(self):
- device = self.lb.current()
-
- if not device:
- self.installer.intf.messageWindow(_("Unable To Delete"),
- _("You must first select a partition to delete."))
- return
-
- if device.type == "lvmvg":
- text = _("Do you really want to delete the selected Logical Volume Group and "
- "all its Logical Volumes?")
- else:
- text = _("Do you really want to delete the selected partition?")
-
- if not self.installer.intf.messageWindow(_("Confirm Delete"), text, type="yesno"):
- return
-
- self.storage.destroyDevice(device)
-
- def __call__(self, installer):
- self.installer = installer
- self.screen = self.installer.intf.screen
- self.storage = self.installer.ds.storage
-
- self.installer.intf.setHelpline(_("F2-New F3-Edit F4-Delete F5-Reset F12-OK"))
-
- self.g = GridForm(self.screen, _("Partitioning"), 1, 5)
- self.lb = CListbox(height=10, cols=4,
- col_widths=[22,14,14,10],
- scroll=1, returnExit = 1,
- width=70, col_pad=2,
- col_labels=[_('Device'), _('Mount Point'), _("Filesystem"), _('Size') ],
- col_label_align=[LEFT, LEFT, LEFT, CENTER])
- self.g.add(self.lb, 0, 1)
-
- self.bb = ButtonBar(self.screen, ((_("New"), "new", "F2"),
- (_("Edit"), "edit", "F3"),
- (_("Delete"), "delete", "F4"),
- TEXT_OK_BUTTON, TEXT_BACK_BUTTON))
-
- self.g.add(self.bb, 0, 2, (0, 1, 0, 0))
- self.g.addHotKey("F5")
-
- while 1:
- self.populate()
- rc = self.g.run()
- button = self.bb.buttonPressed(rc)
-
- if button == "new":
- self.newCb()
- elif button == "edit" or rc == self.lb.listbox: # XXX better way?
- self.editCb()
- elif button == "delete":
- self.deleteCb()
- elif button == "reset" or rc == "F5":
- self.storage.reset()
- elif button == TEXT_BACK_CHECK:
- self.storage.reset()
-
- self.screen.popHelpLine()
- self.screen.popWindow()
- return INSTALL_BACK
- else:
- #if not self.partitions.getRequestByMountPoint("/"):
- # self.intf.messageWindow(_("No Root Partition"),
- # _("Installation requires a / partition."))
- # continue
-
- #(errors, warnings) = self.partitions.sanityCheckAllRequests(self.diskset)
- #rc = partitionSanityErrors(self.intf, errors)
- #if rc != 1:
- # continue
-
- #rc = partitionSanityWarnings(self.intf, warnings)
- #if rc != 1:
- # continue
-
- #warnings = getPreExistFormatWarnings(self.partitions,
- # self.diskset)
- #rc = partitionPreExistFormatWarnings(self.intf, warnings)
- #if rc != 1:
- # continue
-
- self.screen.popHelpLine()
- self.screen.popWindow()
- return INSTALL_OK
-
- return INSTALL_OK
+++ /dev/null
-
-include ../Makefile.inc
-
-POTFILES = ../*.py
-NONPOTFILES = ../lang-table
-
-POS = $(wildcard *.po)
-FMTCATALOGS = $(patsubst %.po,%.mo,$(POS))
-
-MSGMERGE = msgmerge -v
-
-all: $(FMTCATALOGS) report
-
-$(PSNAME).pot: $(POTFILES) $(NONPOTFILES)
- xgettext --from-code=UTF-8 --default-domain=pomona \
- --keyword=_ --keyword=N_ $(POTFILES)
- cat ../lang-table | cut -f1 | while read line; do echo -e "\n#. generated from lang-table\nmsgid \"$$line\"\nmsgstr \"\""; done >> pomona.po
- if cmp -s pomona.po pomona.pot; then \
- rm -f pomona.po; \
- else \
- mv pomona.po pomona.pot; \
- fi
-
-refresh-po:
- for cat in $(POS); do \
- lang=`basename $$cat .po`; \
- if $(MSGMERGE) $$lang.po pomona.pot > $$lang.pot ; then \
- mv -f $$lang.pot $$lang.po ; \
- echo "$(MSGMERGE) of $$lang succeeded" ; \
- else \
- echo "$(MSGMERGE) of $$lang failed" ; \
- rm -f $$lang.pot ; \
- fi \
- done
-
-update-po: $(PSNAME).pot refresh-po
-
-install: all
- mkdir -p $(INSTALLNLSDIR)
- for n in $(FMTCATALOGS); do \
- l=`basename $$n .mo`; \
- $(INSTALL) -m 755 -d $(INSTALLNLSDIR)/$$l; \
- $(INSTALL) -m 755 -d $(INSTALLNLSDIR)/$$l/LC_MESSAGES; \
- $(INSTALL) -m 644 $$n \
- $(INSTALLNLSDIR)/$$l/LC_MESSAGES/pomona.mo; \
- done
-
-%.mo: %.po
- msgfmt --check -o $@ $<
-
-report:
- @for cat in $(POS); do \
- echo -n "$$cat: "; \
- msgfmt -v --statistics -o /dev/null $$cat; \
- done
-
-clean:
- rm -f *.mo missing
+++ /dev/null
-msgid ""
-msgstr ""
-"Project-Id-Version: \n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-01-29 01:02+0100\n"
-"PO-Revision-Date: \n"
-"Last-Translator: Henrik Bro Larsen <hbrolarsen@aktinet.de>\n"
-"Language-Team: <da@li.org>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-#: ../autopart.py:751
-#, python-format
-msgid ""
-"Could not allocate cylinder-based partitions as primary partitions.\n"
-"\n"
-"%s"
-msgstr ""
-"Kunne ikke allokere cylinder-baserede partitioner som primære partitioner.\n"
-"\n"
-"%s"
-
-#: ../autopart.py:756
-#, python-format
-msgid ""
-"Could not allocate partitions as primary partitions.\n"
-"\n"
-"%s"
-msgstr ""
-"Kunne ikke allokere partitioner som primære partitioner.\n"
-"\n"
-"%s"
-
-#: ../autopart.py:761
-#, python-format
-msgid ""
-"Could not allocate cylinder-based partitions.\n"
-"\n"
-"%s"
-msgstr ""
-"Kunne ikke allokere cylinder-baserede partitioner.\n"
-"\n"
-"%s"
-
-#: ../autopart.py:800
-#, python-format
-msgid ""
-"Boot partition %s doesn't belong to a BSD disk label. SRM won't be able to "
-"boot from this partition. Use a partition belonging to a BSD disk label or "
-"change this device disk label to BSD."
-msgstr ""
-"Opstartspartitionen %s tilhører ikke en BSD-disk-etikette. SRM vil ikke "
-"kunne starte fra denne partition. Brug en partition som tilhører en BSD-disk-"
-"etikette eller ændr denne enhedsdisk-etikette til BSD."
-
-#: ../autopart.py:802
-#, python-format
-msgid ""
-"Boot partition %s doesn't belong to a disk with enough free space at its "
-"beginning for the bootloader to live on. Make sure that there's at least 5MB "
-"of free space at the beginning of the disk that contains /boot"
-msgstr ""
-"Startpartitionen %s tilhører ikke en disk med tilstrækkeligt meget ledigt "
-"plads ved dets begyndelse som startprogrammet kan være på. Forsikr dig om at "
-"der findes 5 MB ledigt plads ved begyndelsen af disken som indeholder /boot"
-
-#: ../autopart.py:804
-#, python-format
-msgid ""
-"Boot partition %s isn't a VFAT partition. EFI won't be able to boot from "
-"this partition."
-msgstr ""
-"Startpartitionen %s er ikke en VFAT-partition. EFI vil ikke kunne starte fra "
-"denne partition."
-
-#: ../autopart.py:806
-msgid ""
-"The boot partition must entirely be in the first 4GB of the disk. "
-"OpenFirmware won't be able to boot this installation."
-msgstr ""
-"Startpartitionen skal være placeret fuldtud inden for de første 4 GB på "
-"disken. OpenFirmware vil ikke kunne opstarte denne installation."
-
-#: ../autopart.py:813
-#, python-format
-msgid ""
-"Boot partition %s may not meet booting constraints for your architecture."
-msgstr ""
-"Opstartspartition %s opfylder muligvis ikke opstartsbegrænsningene for din "
-"maskinarkitektur. "
-
-#: ../autopart.py:951
-msgid "Requested Partition Does Not Exist"
-msgstr "Forespurgt partition eksisterer ikke"
-
-#: ../autopart.py:952
-#, python-format
-msgid ""
-"Unable to locate partition %s to use for %s.\n"
-"\n"
-"Press 'OK' to reboot your system."
-msgstr ""
-"Kan ikke finde partition %s som skal bruges til %s.\n"
-"\n"
-"Tryk O.k. for at genstarte systemet."
-
-#: ../autopart.py:997 ../autopart.py:1029
-msgid "Automatic Partitioning Errors"
-msgstr "Fejl ved automatisk partitionering"
-
-#: ../autopart.py:998
-#, python-format
-msgid ""
-"The following errors occurred with your partitioning:\n"
-"\n"
-"%s\n"
-"\n"
-"Press 'OK' to reboot your system."
-msgstr ""
-"Følgende fejl opstod under din partitionering:\n"
-"\n"
-"%s\n"
-"\n"
-"Tryk O.k. for at genstarte systemet."
-
-#: ../autopart.py:1007
-msgid "Warnings During Automatic Partitioning"
-msgstr "Advarsler under automatisk partitionering"
-
-#: ../autopart.py:1008
-#, python-format
-msgid ""
-"Following warnings occurred during automatic partitioning:\n"
-"\n"
-"%s"
-msgstr ""
-"Følgende advarsler opstod under automatisk partitionering:\n"
-"\n"
-"%s"
-
-#: ../autopart.py:1016 ../tui_partition.py:177
-msgid "Error Partitioning"
-msgstr "Fejl under partitionering"
-
-#: ../autopart.py:1017
-#, python-format
-msgid ""
-"Could not allocate requested partitions: \n"
-"\n"
-"%s."
-msgstr ""
-"Kunne ikke allokere forespurgte partitioner: \n"
-"\n"
-"%s."
-
-#: ../autopart.py:1027
-msgid ""
-"\n"
-"\n"
-"Press 'OK' to choose a different partitioning option."
-msgstr ""
-"\n"
-"\n"
-"Tryk 'O.k.' for at vælge en anden partitioneringsoption."
-
-#: ../autopart.py:1030
-#, python-format
-msgid ""
-"The following errors occurred with your partitioning:\n"
-"\n"
-"%s\n"
-"\n"
-"This can happen if there is not enough space on your hard drive(s) for the "
-"installation. %s"
-msgstr ""
-"De følgende fejl opstod med din partitionering:\n"
-"\n"
-"%s\n"
-"\n"
-"Dette kan ske hvis der ikke findes tilstrækkeligt med plads til "
-"installationen på dine diske. %s"
-
-#: ../autopart.py:1105 ../bootloader.py:745 ../partedUtils.py:230
-#: ../partedUtils.py:531 ../partedUtils.py:568 ../tui_bootloader.py:119
-#: ../tui_bootloader.py:439 ../tui_partition.py:182
-msgid "Warning"
-msgstr "Advarsel"
-
-#: ../autopart.py:1126
-msgid ""
-"Automatic Partitioning sets partitions based on the selected installation "
-"type. You also can customize the partitions once they have been created.\n"
-"\n"
-"The manual disk partitioning tool, Disk Druid, allows you to create "
-"partitions in an interactive environment. You can set the file system types, "
-"mount points, partition sizes, and more."
-msgstr ""
-"Automatisk partitionering opsætter partitioner baseret på den valgte "
-"installationstype. Du kan også tilpasse partitionerne efter at de er blevet "
-"oprettet.\n"
-"\n"
-"Værktøjet for manuel partitionering, Disk Druid, lader dig opsætte dine "
-"partitioner i et interaktivt miljø. Du kan sætte filsystemtyper, "
-"monteringspunkter, størrelse på partitioner med mere."
-
-#: ../autopart.py:1137
-msgid ""
-"Before automatic partitioning can be set up by the installation program, you "
-"must choose how to use the space on your hard drives."
-msgstr ""
-"Før automatisk partitionering kan sættes op af installationsprogrammet skal "
-"du vælge hvordan pladsen på harddiskene skal bruges."
-
-#: ../autopart.py:1142
-msgid "Remove all partitions on this system"
-msgstr "Fjern alle partitioner på dette system"
-
-#: ../autopart.py:1144
-#, python-format
-msgid ""
-"You have chosen to remove all partitions (ALL DATA) on the following drives:%"
-"s\n"
-"Are you sure you want to do this?"
-msgstr ""
-"Du har valgt at fjerne alle partitioner (ALLE DATA) på de følgende drev:%s\n"
-"Er du sikker på at du vil gøre dette?"
-
-#: ../bootloader.py:696
-msgid "Bootloader"
-msgstr "Opstartsindlæser"
-
-#: ../bootloader.py:696
-msgid "Installing bootloader..."
-msgstr "Installerer bootloader..."
-
-#: ../bootloader.py:746
-msgid ""
-"No kernel packages were installed on your system. Your boot loader "
-"configuration will not be changed."
-msgstr ""
-"Ingen kernel pakker blev installeret på dit system. Konfigurationen af din "
-"boot loader vil ikke blive ændret."
-
-#: ../constants.py:41
-#, python-format
-msgid ""
-"An unhandled exception has occurred. This is most likely a bug. Please "
-"save a copy of the detailed exception and file a bug report against pomona "
-"at %s"
-msgstr ""
-"En ubehandlet hændelse er sket. Dette er sandsynligvis en fejl. Kopiér den "
-"fulde tekst fra denne undtagelse, og udfyld så en fejlrapport om pomona på %s"
-
-#: ../constants.py:83 ../installer.py:93 ../tui_confirm.py:28
-#: ../tui_network.py:65 ../tui_network.py:74 ../tui.py:224 ../tui.py:390
-msgid "OK"
-msgstr "O.k."
-
-#: ../constants.py:87 ../partIntfHelpers.py:150 ../partIntfHelpers.py:392
-#: ../tui_bootloader.py:194 ../tui.py:103 ../tui.py:104 ../tui.py:393
-msgid "Cancel"
-msgstr "Annullér"
-
-#: ../constants.py:91 ../tui_confirm.py:28 ../tui_confirm.py:30
-msgid "Back"
-msgstr "Tilbage"
-
-#: ../constants.py:95 ../tui_bootloader.py:67 ../tui.py:388
-msgid "Yes"
-msgstr "Ja"
-
-#: ../constants.py:99 ../tui_bootloader.py:67 ../tui.py:389
-msgid "No"
-msgstr "Nej"
-
-#: ../constants.py:103 ../tui_bootloader.py:270 ../tui_partition.py:849
-msgid "Edit"
-msgstr "Redigér"
-
-#: ../fsset.py:422
-msgid "Checking"
-msgstr ""
-
-#: ../fsset.py:423
-#, fuzzy, python-format
-msgid "Checking filesystem on %s..."
-msgstr "Kontrollerer for dårlige blokke på /dev/%s..."
-
-#: ../fsset.py:434
-msgid "Resizing"
-msgstr ""
-
-#: ../fsset.py:435
-#, fuzzy, python-format
-msgid "Resizing filesystem on %s..."
-msgstr "Formaterer %s-filsystem..."
-
-#: ../fsset.py:578 ../fsset.py:1112 ../fsset.py:1143 ../fsset.py:1205
-#: ../fsset.py:1216 ../fsset.py:1270 ../fsset.py:1281 ../fsset.py:1303
-#: ../fsset.py:1352 ../fsset.py:1433 ../partIntfHelpers.py:289
-msgid "Error"
-msgstr "Fejl"
-
-#: ../fsset.py:579
-#, python-format
-msgid ""
-"An error occurred migrating %s to ext3. It is possible to continue without "
-"migrating this file system if desired.\n"
-"\n"
-"Would you like to continue without migrating %s?"
-msgstr ""
-"En fejl opstod under migrering af %s til ext3. Det er muligt at fortsætte om "
-"ønsket uden at migrere filsystemet.\n"
-"\n"
-"Ønsker du at fortsætte uden at migrere %s?"
-
-#: ../fsset.py:1046
-msgid "First sector of boot partition"
-msgstr "Første sektor på opstartspartitionen"
-
-#: ../fsset.py:1047
-msgid "Master Boot Record (MBR)"
-msgstr "Master Boot Record (MBR)"
-
-#: ../fsset.py:1113
-#, python-format
-msgid ""
-"An error occurred trying to initialize swap on device %s. This problem is "
-"serious, and the install cannot continue.\n"
-"\n"
-"Press <Enter> to reboot your system."
-msgstr ""
-"En fejl opstod under forsøg på at initiere swap på enhed %s. Dette problem "
-"er alvorligt, og installationen kan ikke fortsætte.\n"
-"\n"
-"Tryk <Enter> for at starte systemet igen."
-
-#: ../fsset.py:1142
-msgid "Skip"
-msgstr "Overspring"
-
-#: ../fsset.py:1142 ../tui_complete.py:40
-msgid "Reboot"
-msgstr "Genstart"
-
-#: ../fsset.py:1163
-#, python-format
-msgid ""
-"The swap device:\n"
-"\n"
-" /dev/%s\n"
-"\n"
-"is a version 0 Linux swap partition. If you want to use this device, you "
-"must reformat as a version 1 Linux swap partition. If you skip it, the "
-"installer will ignore it during the installation."
-msgstr ""
-"Swapenheden:\n"
-"\n"
-" /dev/%s\n"
-"\n"
-"er en Linuxswappartition af typen version 0. Hvis du vil bruge denne enhed "
-"skal du omformatere den til en Linuxswappartition af typen version 1. Hvis "
-"du springer over det vil installationsprogrammet overspringe det under "
-"installationen."
-
-#: ../fsset.py:1170
-msgid "Reformat"
-msgstr "Omformatér"
-
-#: ../fsset.py:1174
-#, python-format
-msgid ""
-"The swap device:\n"
-"\n"
-" /dev/%s\n"
-"\n"
-"in your /etc/fstab file is currently in use as a software suspend partition, "
-"which means your system is hibernating. To perform an upgrade, please shut "
-"down your system rather than hibernating it."
-msgstr ""
-"Swapenheden:\n"
-"\n"
-" /dev/%s\n"
-"\n"
-"i din /etc/fstab-fil bruges i øjeblikket som en partition for "
-"programsuspendering, hvilket betyder at dit system er i hviletilstand. For "
-"at lave en opgradering bør du lukke dit system ned i stedet for at sætte det "
-"i hviletilstand."
-
-#: ../fsset.py:1182
-#, python-format
-msgid ""
-"The swap device:\n"
-"\n"
-" /dev/%s\n"
-"\n"
-"in your /etc/fstab file is currently in use as a software suspend partition, "
-"which means your system is hibernating. If you are performing a new install, "
-"make sure the installer is set to format all swap partitions."
-msgstr ""
-"Swapenheden:\n"
-"\n"
-" /dev/%s\n"
-"\n"
-"i din /etc/fstab-fil bruges i øjeblikket som en partition for "
-"programsuspendering, det vil sige at dit system er i hviletilstand. Hvis du "
-"er i gang med en ny installation bør du se til at installationsprogrammet er "
-"sat op til at formatere alle swappartitioner."
-
-#: ../fsset.py:1192
-msgid ""
-"\n"
-"\n"
-"Choose Skip if you want the installer to ignore this partition during the "
-"upgrade. Choose Format to reformat the partition as swap space. Choose "
-"Reboot to restart the system."
-msgstr ""
-"\n"
-"\n"
-"Vælg overspring hvis du ønsker at installationsprogrammet skal ignorere "
-"denne partition under opgraderingen. Vælg Formatér for at genformatere "
-"partitionen som swapplads. Vælg Genstart for at genstarte systemet."
-
-#: ../fsset.py:1198
-msgid "Format"
-msgstr "Formatér"
-
-#: ../fsset.py:1206
-#, python-format
-msgid ""
-"Error enabling swap device %s: %s\n"
-"\n"
-"The /etc/fstab on your upgrade partition does not reference a valid swap "
-"partition.\n"
-"\n"
-"Press OK to reboot your system."
-msgstr ""
-"Fejl under aktivering af swap-enhed %s: %s\n"
-"\n"
-"Filen /etc/fstab på din opgraderingspartition henviser ikke til en gyldig "
-"swap-partition.\n"
-"\n"
-"Tryk O.k. for at genstarte systemet."
-
-#: ../fsset.py:1217
-#, python-format
-msgid ""
-"Error enabling swap device %s: %s\n"
-"\n"
-"This most likely means this swap partition has not been initialized.\n"
-"\n"
-"Press OK to reboot your system."
-msgstr ""
-"Fejl under aktivering af swap-enhed %s: %s\n"
-"\n"
-"Dette betyder sandsynligvis at swap-partitionen ikke er initieret.\n"
-"\n"
-"Tryk O.k. for at genstarte systemet."
-
-#: ../fsset.py:1271
-#, python-format
-msgid ""
-"Bad blocks have been detected on device /dev/%s. We do not recommend you use "
-"this device.\n"
-"\n"
-"Press <Enter> to reboot your system"
-msgstr ""
-"Der er fundet dårlige blokke på enhed /dev/%s. Vi anbefaler ikke at du "
-"bruger denne enhed.\n"
-"\n"
-"Tryk <Enter> for genstarte systemet."
-
-#: ../fsset.py:1282
-#, python-format
-msgid ""
-"An error occurred searching for bad blocks on %s. This problem is serious, "
-"and the install cannot continue.\n"
-"\n"
-"Press <Enter> to reboot your system."
-msgstr ""
-"En fejl opstod under søgning efter dårlige blokke på %s. Dette problem er "
-"alvorligt, og installationen kan ikke fortsætte.\n"
-"\n"
-"Tryk <Enter> for at genstarte systemet."
-
-#: ../fsset.py:1304
-#, python-format
-msgid ""
-"An error occurred trying to format %s. This problem is serious, and the "
-"install cannot continue.\n"
-"\n"
-"Press <Enter> to reboot your system."
-msgstr ""
-"Der opstod en fejl ved forsøg på formatering af %s. Dette problem er så "
-"alvorligt, at installationen ikke kan fortsætte.\n"
-"\n"
-"Tryk på return for at genstarte systemet."
-
-#: ../fsset.py:1353
-#, python-format
-msgid ""
-"An error occurred trying to migrate %s. This problem is serious, and the "
-"install cannot continue.\n"
-"\n"
-"Press <Enter> to reboot your system."
-msgstr ""
-"Der opstod en fejl ved migrering af %s. Dette problem er så alvorligt, at "
-"installationen ikke kan fortsætte.\n"
-"\n"
-"Tryk på return for at genstarte systemet."
-
-#: ../fsset.py:1380 ../fsset.py:1389
-msgid "Invalid mount point"
-msgstr "Ugyldigt monteringspunkt"
-
-#: ../fsset.py:1381
-#, python-format
-msgid ""
-"An error occurred when trying to create %s. Some element of this path is "
-"not a directory. This is a fatal error and the install cannot continue.\n"
-"\n"
-"Press <Enter> to reboot your system."
-msgstr ""
-"Der opstod en fejl ved forsøg på oprettelse af %s. Elementer af denne sti er "
-"ikke et katalog. Dette problem er så alvorligt, at installationen ikke kan "
-"fortsætte.\n"
-"\n"
-"Tryk på return for at genstarte systemet."
-
-#: ../fsset.py:1390
-#, python-format
-msgid ""
-"An error occurred when trying to create %s: %s. This is a fatal error and "
-"the install cannot continue.\n"
-"\n"
-"Press <Enter> to reboot your system."
-msgstr ""
-"Der opstod en fejl ved forsøg på oprettelse af %s: %s. Dette problem er så "
-"alvorligt, at installationen ikke kan fortsætte.\n"
-"\n"
-"Tryk på return for at genstarte systemet."
-
-#: ../fsset.py:1403
-msgid "Unable to mount filesystem"
-msgstr "Kan ikke montere filsystem"
-
-#: ../fsset.py:1404
-#, python-format
-msgid ""
-"An error occurred mounting device %s as %s. You may continue installation, "
-"but there may be problems."
-msgstr ""
-"Et fejl skete ved montering af enhed %s som %s. Du kan fortsætte "
-"installationen men det kan opstå problemer."
-
-#: ../fsset.py:1411 ../fsset.py:1820 ../fsset.py:1827 ../packages.py:131
-#: ../partedUtils.py:578 ../tui_confirm.py:37
-msgid "_Reboot"
-msgstr "_Genstart"
-
-#: ../fsset.py:1411 ../partedUtils.py:578
-msgid "_Continue"
-msgstr "_Fortsæt"
-
-#: ../fsset.py:1419
-#, python-format
-msgid ""
-"Error mounting device %s as %s: %s\n"
-"\n"
-"Devices in /etc/fstab should be specified by label, not by device name.\n"
-"\n"
-"Press OK to reboot your system."
-msgstr ""
-"Fejl ved montering af enhed %s som %s: %s\n"
-"\n"
-"Enheder i /etc/fstab bør angives ved label, ikke ved enhedsnavn.\n"
-"\n"
-"Tryk O.k. for at genstarte, dit system."
-
-#: ../fsset.py:1426
-#, python-format
-msgid ""
-"Error mounting device %s as %s: %s\n"
-"\n"
-"This most likely means this partition has not been formatted.\n"
-"\n"
-"Press OK to reboot your system."
-msgstr ""
-"Fejl ved montering af enhed %s som %s: %s\n"
-"\n"
-"Dette betyder højst sandsynligt at denne partition ikke er blevet "
-"formateret.\n"
-"\n"
-"Tryk O.k. for at genstarte dit system."
-
-#: ../fsset.py:1812
-msgid "Duplicate Labels"
-msgstr "Doppelte etiketter"
-
-#: ../fsset.py:1813
-#, python-format
-msgid ""
-"Multiple devices on your system are labelled %s. Labels across devices must "
-"be unique for your system to function properly.\n"
-"\n"
-"Please fix this problem and restart the installation process."
-msgstr ""
-"Flere enheder på dit system er benævnt %s. Etiketter skal være unikke for "
-"hver enhed på dit system for at fungere rigtigt.\n"
-"\n"
-"Ret dette problem og genstart installationsprocessen."
-
-#: ../fsset.py:1822
-msgid "Invalid Label"
-msgstr "Ugyldig etikette"
-
-#: ../fsset.py:1823
-#, python-format
-msgid ""
-"An invalid label was found on device %s. Please fix this problem and "
-"restart the installation process."
-msgstr ""
-"En ugyldig etikette blev fundet på enhed %s. Ret dette problem og genstart "
-"installationsprocessen."
-
-#: ../fsset.py:2049
-msgid "Formatting"
-msgstr "Formaterer"
-
-#: ../fsset.py:2050
-#, python-format
-msgid "Formatting %s file system..."
-msgstr "Formaterer %s-filsystem..."
-
-#: ../installer.py:88
-msgid "Fatal Error"
-msgstr "Alvorlig fejl"
-
-#: ../installer.py:89
-#, python-format
-msgid ""
-"You do not have enough RAM to install %s on this machine.\n"
-"\n"
-"Press <return> to reboot your system.\n"
-msgstr ""
-"Du har ikke RAM nok til at installere %s på denne maskine.\n"
-"Tast <return> for at genstarte systemet.\n"
-
-#: ../installer.py:173
-msgid "Starting text installation..."
-msgstr "Starter text-baseret installation..."
-
-#: ../keyboard_models.py:48
-msgid "keyboard|Arabic (azerty)"
-msgstr "tastatur|Arabisk (azerty)"
-
-#: ../keyboard_models.py:51
-msgid "keyboard|Arabic (azerty/digits)"
-msgstr "tastatur|Arabisk (azerty/numerisk tastatur)"
-
-#: ../keyboard_models.py:54
-msgid "keyboard|Arabic (digits)"
-msgstr "tastatur|Arabisk (numerisk tastatur)"
-
-#: ../keyboard_models.py:57
-msgid "keyboard|Arabic (qwerty)"
-msgstr "tastatur|Arabisk (qwerty)"
-
-#: ../keyboard_models.py:60
-msgid "keyboard|Arabic (qwerty/digits)"
-msgstr "tastatur|arabisk (qwerty/numerisk tastatur)"
-
-#: ../keyboard_models.py:63
-msgid "keyboard|Belgian (be-latin1)"
-msgstr "tastatur|Belgisk (be-latin1)"
-
-#: ../keyboard_models.py:66
-msgid "keyboard|Bengali (Inscript)"
-msgstr "tastatur|Bengalsk (Inscript)"
-
-#: ../keyboard_models.py:69
-msgid "keyboard|Bengali (Probhat)"
-msgstr "tastatur|Bengalsk (Probhat)"
-
-#: ../keyboard_models.py:72
-msgid "keyboard|Bulgarian"
-msgstr "tastatur|Bulgarsk"
-
-#: ../keyboard_models.py:75
-msgid "keyboard|Bulgarian (Phonetic)"
-msgstr "tastatur|Bulgarsk (phonetisk)"
-
-#: ../keyboard_models.py:78
-msgid "keyboard|Brazilian (ABNT2)"
-msgstr "tastatur|Brasiliansk (ABNT2)"
-
-#: ../keyboard_models.py:81
-msgid "keyboard|French Canadian"
-msgstr "tastatur|fransk kanadisk"
-
-#: ../keyboard_models.py:84
-msgid "keyboard|Croatian"
-msgstr "tastatur|Kroatisk"
-
-#: ../keyboard_models.py:87
-msgid "keyboard|Czech"
-msgstr "tastatur|Tjekkisk"
-
-#: ../keyboard_models.py:90
-msgid "keyboard|Czech (qwerty)"
-msgstr "tastatur|Tjekkisk (qwerty)"
-
-#: ../keyboard_models.py:93
-msgid "keyboard|German"
-msgstr "tastatur|Tysk"
-
-#: ../keyboard_models.py:96
-msgid "keyboard|German (latin1)"
-msgstr "tastatur|Tysk (latin1)"
-
-#: ../keyboard_models.py:99
-msgid "keyboard|German (latin1 w/ no deadkeys)"
-msgstr "tastatur|Tysk (latin1 uden døde taster)"
-
-#: ../keyboard_models.py:102
-msgid "keyboard|Devanagari (Inscript)"
-msgstr "tastatur|Devanagarisk (Inscript)"
-
-#: ../keyboard_models.py:105
-msgid "keyboard|Dvorak"
-msgstr "tastatur|Dvorak"
-
-#: ../keyboard_models.py:108
-msgid "keyboard|Danish"
-msgstr "tastatur|Dansk"
-
-#: ../keyboard_models.py:111
-msgid "keyboard|Danish (latin1)"
-msgstr "tastatur|Dansk (latin1)"
-
-#: ../keyboard_models.py:114
-msgid "keyboard|Spanish"
-msgstr "tastatur|Spansk"
-
-#: ../keyboard_models.py:117
-msgid "keyboard|Estonian"
-msgstr "tastatur|Estisk"
-
-#: ../keyboard_models.py:120
-msgid "keyboard|Finnish"
-msgstr "tastatur|Finsk"
-
-#: ../keyboard_models.py:123
-msgid "keyboard|Finnish (latin1)"
-msgstr "tastatur|Finsk (latin1)"
-
-#: ../keyboard_models.py:126
-msgid "keyboard|French"
-msgstr "tastatur|Fransk"
-
-#: ../keyboard_models.py:129
-msgid "keyboard|French (latin9)"
-msgstr "tastatur|Fransk (latin9)"
-
-#: ../keyboard_models.py:132
-msgid "keyboard|French (latin1)"
-msgstr "tastatur|Fransk (latin1)"
-
-#: ../keyboard_models.py:135
-msgid "keyboard|French (pc)"
-msgstr "tastatur|Fransk (pc)"
-
-#: ../keyboard_models.py:138
-msgid "keyboard|Swiss French"
-msgstr "tastatur|Svejtsisk-fransk"
-
-#: ../keyboard_models.py:141
-msgid "keyboard|Swiss French (latin1)"
-msgstr "tastatur|Svejtsisk-fransk (latin1)"
-
-#: ../keyboard_models.py:144
-msgid "keyboard|Greek"
-msgstr "tastatur|græsk"
-
-#: ../keyboard_models.py:147
-#, fuzzy
-msgid "keyboard|Gujarati (Inscript)"
-msgstr "tastatur|Punjabi (Inscript)"
-
-#: ../keyboard_models.py:150
-msgid "keyboard|Punjabi (Inscript)"
-msgstr "tastatur|Punjabi (Inscript)"
-
-#: ../keyboard_models.py:153
-msgid "keyboard|Hungarian"
-msgstr "tastatur|Ungarsk"
-
-#: ../keyboard_models.py:156
-msgid "keyboard|Hungarian (101 key)"
-msgstr "tastatur|Ungarsk (101 taster)"
-
-#: ../keyboard_models.py:159
-msgid "keyboard|Icelandic"
-msgstr "tastatur|Islandsk"
-
-#: ../keyboard_models.py:162
-msgid "keyboard|Italian"
-msgstr "tastatur|Italiensk"
-
-#: ../keyboard_models.py:165
-msgid "keyboard|Italian (IBM)"
-msgstr "tastatur|Italiensk (IBM)"
-
-#: ../keyboard_models.py:168
-msgid "keyboard|Italian (it2)"
-msgstr "tastatur|Italiensk (it2)"
-
-#: ../keyboard_models.py:171
-msgid "keyboard|Japanese"
-msgstr "tastatur|Japansk"
-
-#: ../keyboard_models.py:174
-msgid "keyboard|Korean"
-msgstr "tastatur|Koreansk"
-
-#: ../keyboard_models.py:177
-msgid "keyboard|Latin American"
-msgstr "tastatur|latinamerika"
-
-#: ../keyboard_models.py:180
-msgid "keyboard|Macedonian"
-msgstr "tastatur|Makedonsk"
-
-#: ../keyboard_models.py:183
-msgid "keyboard|Dutch"
-msgstr "tastatur|Hollandsk"
-
-#: ../keyboard_models.py:186
-msgid "keyboard|Norwegian"
-msgstr "tastatur|Norsk"
-
-#: ../keyboard_models.py:189
-msgid "keyboard|Polish"
-msgstr "tastatur|Polsk"
-
-#: ../keyboard_models.py:192
-msgid "keyboard|Portuguese"
-msgstr "tastatur|Portugisisk"
-
-#: ../keyboard_models.py:195
-msgid "keyboard|Romanian"
-msgstr "tastatur|Rumænsk"
-
-#: ../keyboard_models.py:198
-msgid "keyboard|Russian"
-msgstr "tastatur|Russisk"
-
-#: ../keyboard_models.py:201
-msgid "keyboard|Serbian"
-msgstr "tastatur|Serbisk"
-
-#: ../keyboard_models.py:204
-msgid "keyboard|Serbian (latin)"
-msgstr "tastatur|Serbisk (Latinsk)"
-
-#: ../keyboard_models.py:207
-msgid "keyboard|Swedish"
-msgstr "tastatur|Svensk"
-
-#: ../keyboard_models.py:210
-msgid "keyboard|Swiss German"
-msgstr "tastatur|Svejtsisk-tysk"
-
-#: ../keyboard_models.py:213
-msgid "keyboard|Swiss German (latin1)"
-msgstr "tastatur|Svejtsisk-tysk (latin1)"
-
-#: ../keyboard_models.py:216
-msgid "keyboard|Slovak (qwerty)"
-msgstr "tastatur|Slovakisk (qwerty)"
-
-#: ../keyboard_models.py:219
-msgid "keyboard|Slovenian"
-msgstr "tastatur||Slovensk"
-
-#: ../keyboard_models.py:222
-msgid "keyboard|Tamil (Inscript)"
-msgstr "tastatur|Tamilsk (Inscript)"
-
-#: ../keyboard_models.py:225
-msgid "keyboard|Tamil (Typewriter)"
-msgstr "tastatur|tamil (typewriter)"
-
-#: ../keyboard_models.py:228
-msgid "keyboard|Turkish"
-msgstr "tastatur|tyrkisk"
-
-#: ../keyboard_models.py:231
-msgid "keyboard|United Kingdom"
-msgstr "tastatur|United Kingdom"
-
-#: ../keyboard_models.py:234
-msgid "keyboard|Ukrainian"
-msgstr "tastatur|Ukrainsk"
-
-#: ../keyboard_models.py:237
-msgid "keyboard|U.S. International"
-msgstr "tastatur|U.S. international"
-
-#: ../keyboard_models.py:240
-msgid "keyboard|U.S. English"
-msgstr "tastatur|U.S. Engelsk"
-
-#: ../network.py:31
-msgid "IP address is missing."
-msgstr ""
-
-#: ../network.py:35
-msgid ""
-"IPv4 addresses must contain four numbers between 0 and 255, separated by "
-"periods."
-msgstr ""
-
-#: ../network.py:38
-#, python-format
-msgid "'%s' is not a valid IPv6 address."
-msgstr ""
-
-#: ../network.py:40
-#, python-format
-msgid "'%s' is an invalid IP address."
-msgstr ""
-
-#: ../network.py:52
-msgid "Hostname must be 255 or fewer characters in length."
-msgstr ""
-
-#: ../network.py:58
-msgid ""
-"Hostname must start with a valid character in the ranges 'a-z', 'A-Z', or '0-"
-"9'"
-msgstr ""
-
-#: ../network.py:63
-msgid ""
-"Hostnames can only contain the characters 'a-z', 'A-Z', '0-9', '-', or '.'"
-msgstr ""
-
-#: ../packages.py:113
-msgid "Warning! This is pre-release software!"
-msgstr "Advarsel! Dette er ikke færdigaftestet programmel!"
-
-#: ../packages.py:114
-#, python-format
-msgid ""
-"Thank you for downloading this pre-release of %s.\n"
-"\n"
-"This is not a final release and is not intended for use on production "
-"systems. The purpose of this release is to collect feedback from testers, "
-"and it is not suitable for day to day usage.\n"
-"\n"
-"To report feedback, please visit:\n"
-"\n"
-" %s\n"
-"\n"
-"and file a report against '%s'.\n"
-msgstr ""
-"Tak for at du har hentet denne tidlige udgave af %s.\n"
-"\n"
-"Dette er ikke den endelige udgave og den er ikke ment til brug på systemer i "
-"produktion. Formålet med denne udgave er at indsamle tilbagemeldinger fra "
-"testere, og den er ikke velegnet til daglig brug.\n"
-"\n"
-"For at indsende tilbagemeldinger skal du besøge:\n"
-"\n"
-" %s\n"
-"\n"
-"og udfylde en fejlrapport om '%s'.\n"
-
-#: ../packages.py:127
-msgid "_Exit"
-msgstr "_Afslut"
-
-#: ../packages.py:127
-msgid "_Install anyway"
-msgstr "_Installér alligevel"
-
-#: ../packages.py:130
-msgid "Your system will now be rebooted..."
-msgstr "Dit system vil nu blive genstartet.."
-
-#: ../packages.py:131 ../tui_confirm.py:37
-msgid "_Back"
-msgstr "_Tilbage"
-
-#: ../packages.py:132
-msgid "Rebooting System"
-msgstr "Genstarter system"
-
-#: ../pakfireinstall.py:47
-#, python-format
-msgid "%s MB"
-msgstr "%s MB"
-
-#: ../pakfireinstall.py:50
-#, python-format
-msgid "%s KB"
-msgstr "%s kB"
-
-#: ../pakfireinstall.py:53
-#, python-format
-msgid "%s Byte"
-msgstr "%s byte"
-
-#: ../pakfireinstall.py:55
-#, python-format
-msgid "%s Bytes"
-msgstr "%s byte"
-
-#: ../pakfireinstall.py:134
-msgid "Base system"
-msgstr "Basis system"
-
-#: ../pakfireinstall.py:134
-msgid "Installing base system..."
-msgstr "Installerer basis systemet..."
-
-#: ../pakfireinstall.py:171
-msgid "Install Starting"
-msgstr "Installationen starter"
-
-#: ../pakfireinstall.py:172
-msgid "Starting install process. This may take several minutes..."
-msgstr "Starter installationsproces. Dette kan tage op til flere minutter..."
-
-#: ../pakfireinstall.py:183
-msgid "Post Install"
-msgstr "Efter installation"
-
-#: ../pakfireinstall.py:184
-msgid "Performing post install configuration..."
-msgstr "Konfigurerer systemet efter installation..."
-
-#: ../pakfireinstall.py:215
-msgid "Symmetric multiprocessing"
-msgstr "Symmetrisk multiprocessing"
-
-#: ../pakfireinstall.py:216
-msgid "Xen guest"
-msgstr "Xen gæst"
-
-#: ../pakfireinstall.py:226
-msgid "Normal Boot"
-msgstr "Normal opstart"
-
-#: ../pakfireinstall.py:233
-msgid "Installation Progress"
-msgstr "Installationsfremskridt"
-
-#: ../partedUtils.py:191 ../tui_partition.py:408
-msgid "Foreign"
-msgstr "Fremmed"
-
-#: ../partedUtils.py:231
-#, python-format
-msgid ""
-"/dev/%s currently has a %s partition layout. To use this drive for the "
-"installation of %s, it must be re-initialized, causing the loss of ALL DATA "
-"on this drive.\n"
-"\n"
-"Would you like to re-initialize this drive?"
-msgstr ""
-"/dev/%s har i øjeblikket et %s partitions layout. For at bruge dette "
-"diskdrev til installationen af %s, skal den først re-initialiseres, hvilket "
-"medfører tab af ALLE DATA på dette diskdrev.\n"
-"\n"
-"Ønsker du at re-initiere dette diskdrev?"
-
-#: ../partedUtils.py:239
-msgid "_Ignore drive"
-msgstr "Ignorér drev"
-
-#: ../partedUtils.py:240
-msgid "_Re-initialize drive"
-msgstr "_Re-initialisér diskdrev"
-
-#: ../partedUtils.py:532
-#, python-format
-msgid ""
-"The partition table on device %s was unreadable. To create new partitions it "
-"must be initialized, causing the loss of ALL DATA on this drive.\n"
-"\n"
-"This operation will override any previous installation choices about which "
-"drives to ignore.\n"
-"\n"
-"Would you like to initialize this drive, erasing ALL DATA?"
-msgstr ""
-"Partitionstabellen på enhed %s er ulæselig. For at oprette nye partitioner "
-"skal den initieres, hvilket vil ødelægge ALLE DATA på denne enhed.\n"
-"\n"
-"Denne handling vil tilsidesætte alle tidligere valg under installationen om "
-"hvilke enheder der skal ignoreres.\n"
-"\n"
-"Vil du initiere denne enhed og fjerne ALLE DATA?"
-
-#: ../partedUtils.py:569
-#, python-format
-msgid ""
-"The drive /dev/%s has more than 15 partitions on it. The SCSI subsystem in "
-"the Linux kernel does not allow for more than 15 partitons at this time. "
-"You will not be able to make changes to the partitioning of this disk or use "
-"any partitions beyond /dev/%s15 in %s"
-msgstr ""
-"Diskdrevet /dev/%s indeholder mere end 15 partitioner. SCSI-undersystemet i "
-"Linux-kernen tillader i øjeblikket ikke mere end 15 partitoner. Du vil "
-"ikke kunne lave ændringer af partitioneringen af dette diskdrev eller bruge "
-"nogen partitioner ud over /dev/%s15 i %s"
-
-#: ../partedUtils.py:659
-msgid "No Drives Found"
-msgstr "Ingen drev fundet"
-
-#: ../partedUtils.py:660
-msgid ""
-"An error has occurred - no valid devices were found on which to create new "
-"file systems. Please check your hardware for the cause of this problem."
-msgstr ""
-"En fejl er opstået - ingen gyldige enheder blev fundet på hvilke nye "
-"filsystemer kunne oprettes. Tjek venligst din maskine for at finde grunden "
-"til dette problem."
-
-#: ../partIntfHelpers.py:50
-#, python-format
-msgid ""
-"The mount point %s is invalid. Mount points must start with '/' and cannot "
-"end with '/', and must contain printable characters and no spaces."
-msgstr ""
-"Monteringspunktet %s er ugyldigt. Monteringspunkter skal begynde med '/', "
-"kan ikke slutte med '/', og skal indeholde udskrivbare tegn og ingen blanke."
-
-#: ../partIntfHelpers.py:57
-msgid "Please specify a mount point for this partition."
-msgstr "Specificér et monteringspunkt for denne partition."
-
-#: ../partIntfHelpers.py:74 ../partIntfHelpers.py:80 ../partIntfHelpers.py:90
-#: ../partIntfHelpers.py:111
-msgid "Unable To Delete"
-msgstr "Kan ikke fjerne"
-
-#: ../partIntfHelpers.py:75
-msgid "You must first select a partition to delete."
-msgstr "Du skal først vælge en partition som skal fjernes."
-
-#: ../partIntfHelpers.py:81
-msgid "You cannot delete free space."
-msgstr "Du kan ikke fjerne ledig plads."
-
-#: ../partIntfHelpers.py:91
-#, python-format
-msgid ""
-"You cannot delete this partition, as it is an extended partition which "
-"contains %s"
-msgstr ""
-"Du kan ikke slette denne partition, da den er en udvidet partition som "
-"indeholder %s"
-
-#: ../partIntfHelpers.py:106
-msgid "This partition is holding the data for the hard drive install."
-msgstr "Denne partition indeholder data for harddiskinstallationen."
-
-#: ../partIntfHelpers.py:112
-msgid ""
-"You cannot delete this partition:\n"
-"\n"
-msgstr ""
-"Du kan ikke slette denne partition:\n"
-"\n"
-
-#: ../partIntfHelpers.py:146 ../partIntfHelpers.py:391
-msgid "Confirm Delete"
-msgstr "Bekræft sletning"
-
-#: ../partIntfHelpers.py:147
-#, python-format
-msgid "You are about to delete all partitions on the device '/dev/%s'."
-msgstr "Du er i færd med at slette alle partitioner på enheden /dev/%s."
-
-#: ../partIntfHelpers.py:150 ../partIntfHelpers.py:392
-msgid "_Delete"
-msgstr "_Slet"
-
-#: ../partIntfHelpers.py:206
-msgid "Notice"
-msgstr "Bemærk"
-
-#: ../partIntfHelpers.py:207
-#, python-format
-msgid ""
-"The following partitions were not deleted because they are in use:\n"
-"\n"
-"%s"
-msgstr ""
-"Følgende partitioner blev ikke fjernet da de er i brug:\n"
-"\n"
-"%s"
-
-#: ../partIntfHelpers.py:222 ../partIntfHelpers.py:238
-#: ../partIntfHelpers.py:249
-msgid "Unable To Edit"
-msgstr "Kan ikke redigere"
-
-#: ../partIntfHelpers.py:223
-msgid "You must select a partition to edit"
-msgstr "Du skal vælge en partition for redigering"
-
-#: ../partIntfHelpers.py:239
-#, python-format
-msgid ""
-"You cannot edit this partition, as it is an extended partition which "
-"contains %s"
-msgstr ""
-"Du kan ikke redigere denne partition, da den er en udvidet partition som "
-"indeholder %s"
-
-#: ../partIntfHelpers.py:250
-msgid ""
-"You cannot edit this partition:\n"
-"\n"
-msgstr ""
-"Du kan ikke redigere denne partition:\n"
-"\n"
-
-#: ../partIntfHelpers.py:272
-msgid "Format as Swap?"
-msgstr "Formatér som swap?"
-
-#: ../partIntfHelpers.py:273
-#, python-format
-msgid ""
-"/dev/%s has a partition type of 0x82 (Linux swap) but does not appear to be "
-"formatted as a Linux swap partition.\n"
-"\n"
-"Would you like to format this partition as a swap partition?"
-msgstr ""
-"/dev/%s har partitionstype 0x82 (Linux swap), men ser ikke ud til at være "
-"formateret som en swappartition.\n"
-"\n"
-"Ønsker du at formatere denne partition som en swappartition?"
-
-#: ../partIntfHelpers.py:288
-#, python-format
-msgid "You need to select at least one hard drive to install %s."
-msgstr "Du skal vælge mindst et drev, som du skal installere %s på."
-
-#: ../partIntfHelpers.py:293
-msgid ""
-"You have chosen to use a pre-existing partition for this installation "
-"without formatting it. We recommend that you format this partition to make "
-"sure files from a previous operating system installation do not cause "
-"problems with this installation of Linux. However, if this partition "
-"contains files that you need to keep, such as home directories, then "
-"continue without formatting this partition."
-msgstr ""
-"Du har valgt at bruge en allerede eksisterende partition for denne "
-"installation uden at formatere den. Vi anbefaler at du formaterer denne "
-"partition for at forsikre dig om at filer fra en tidligere "
-"operativsystemsinstallation ikke forårsager problemer med denne installation "
-"af Linux. Hvis denne partition indeholder filer som du vil beholde, som fx "
-"hjemmekataloger, bør du dog fortsætte uden at formatere denne partition."
-
-#: ../partIntfHelpers.py:301
-msgid "Format?"
-msgstr "Formatér?"
-
-#: ../partIntfHelpers.py:302
-msgid "_Modify Partition"
-msgstr "_Ændre partition"
-
-#: ../partIntfHelpers.py:302
-msgid "Do _Not Format"
-msgstr "Formater _ikke"
-
-#: ../partIntfHelpers.py:311
-msgid "Error with Partitioning"
-msgstr "Fejl under partitionering"
-
-#: ../partIntfHelpers.py:312
-#, python-format
-msgid ""
-"The following critical errors exist with your requested partitioning scheme. "
-"These errors must be corrected prior to continuing with your install of %s.\n"
-"\n"
-"%s"
-msgstr ""
-"Følgende kritiske fejl opstod med dit forespurgte partitionsskema. Disse "
-"fejl skal der rettes op på før du fortsætter med installationen af %s.\n"
-"\n"
-"%s"
-
-#: ../partIntfHelpers.py:326
-msgid "Partitioning Warning"
-msgstr "Advarsel fra partitionering"
-
-#: ../partIntfHelpers.py:327
-#, python-format
-msgid ""
-"The following warnings exist with your requested partition scheme.\n"
-"\n"
-"%s\n"
-"\n"
-"Would you like to continue with your requested partitioning scheme?"
-msgstr ""
-"Følgende advarsler opstod med dit partitioneringsoplæg.\n"
-"\n"
-"%s\n"
-"\n"
-"Vil du fortsætte med det forespurgte partitioneringsoplæg?"
-
-#: ../partIntfHelpers.py:340
-msgid ""
-"The following pre-existing partitions have been selected to be formatted, "
-"destroying all data."
-msgstr ""
-"Disse eksisterende partitioner er mærket for formatering, som vil ødelægge "
-"alle data."
-
-#: ../partIntfHelpers.py:342
-msgid ""
-"Select 'Yes' to continue and format these partitions, or 'No' to go back and "
-"change these settings."
-msgstr ""
-"Vælg 'Ja' for at fortsætte med formatering af disse partitioner, eller 'Nej' "
-"for at gå tilbage og ændre disse indstillinger."
-
-#: ../partIntfHelpers.py:348
-msgid "Format Warning"
-msgstr "Formateringsadvarsel"
-
-#: ../partIntfHelpers.py:387
-#, python-format
-msgid "You are about to delete the /dev/%s partition."
-msgstr "Du er i færd med at slette partitionen /dev/%s."
-
-#: ../partIntfHelpers.py:389
-msgid "The partition you selected will be deleted."
-msgstr "Partitionen du markerede vil blive fjernet."
-
-#: ../partIntfHelpers.py:398
-msgid "Confirm Reset"
-msgstr "Bekræft nulstilling"
-
-#: ../partIntfHelpers.py:399
-msgid ""
-"Are you sure you want to reset the partition table to its original state?"
-msgstr ""
-"Er du sikker på at du vil nulstille partitionstabellen til oprindelig "
-"tilstand?"
-
-#: ../partitioning.py:36
-msgid "Installation cannot continue."
-msgstr "Installation kan ikke fortsætte."
-
-#: ../partitioning.py:37
-msgid ""
-"The partitioning options you have chosen have already been activated. You "
-"can no longer return to the disk editing screen. Would you like to continue "
-"with the installation process?"
-msgstr ""
-"Partitionerings optionerne du har valgt er allerede aktiveret. Du vil ikke "
-"kunne gå tilbage til skærmen for redigering af diske. Vil du fortsætte "
-"installationsprocessen?"
-
-#: ../partitioning.py:65
-msgid "Low Memory"
-msgstr "Lav hukommelse"
-
-#: ../partitioning.py:66
-msgid ""
-"As you don't have much memory in this machine, we need to turn on swap space "
-"immediately. To do this we'll have to write your new partition table to the "
-"disk immediately. Is that OK?"
-msgstr ""
-"Da du ikke har ret megen hukommelse på denne maskine, bliver vi nødt til at "
-"starte swap med det samme. For at gøre det er vi nødt at skrive den nye "
-"partitionstabel på disken. Er det i orden?"
-
-#: ../partitions.py:311
-#, python-format
-msgid ""
-"You have not defined a root partition (/), which is required for "
-"installation of %s to continue."
-msgstr ""
-"Du har ikke defineret en rod-partition (/). Dette skal gøres før "
-"installationen af %s kan fortsætte."
-
-#: ../partitions.py:316
-#, python-format
-msgid ""
-"Your root partition is less than 250 megabytes which is usually too small to "
-"install %s."
-msgstr ""
-"Din rod-partition er mindre end 250 megabyte og dette er normalt for lidt "
-"til at installere %s."
-
-#: ../partitions.py:333
-msgid ""
-"Your boot partition isn't on one of the first four partitions and thus won't "
-"be bootable."
-msgstr ""
-"Din opstarts-partition er ikke en af de fire første partitioner og vil "
-"derfor ikke være startbar."
-
-#: ../partitions.py:342
-#, python-format
-msgid ""
-"Your %s partition is less than %s megabytes which is lower than recommended "
-"for a normal %s install."
-msgstr ""
-"Din %s-partition er mindre end %s megabyte og dette er lavere end anbefalet "
-"for en almindelig installation af %s."
-
-#: ../partitions.py:374
-msgid ""
-"Installing on a USB device. This may or may not produce a working system."
-msgstr ""
-"Installerer på en USB-enhed. Dette kan give et fungerende system, men det er "
-"ikke sikkert."
-
-#: ../partitions.py:378
-msgid ""
-"Installing on a FireWire device. This may or may not produce a working "
-"system."
-msgstr ""
-"Installerer på en FireWire-enhed. Dette kan give et fungerende system, men "
-"det er ikke sikkert."
-
-#: ../partitions.py:391
-msgid ""
-"You have not specified a swap partition. Although not strictly required in "
-"all cases, it will significantly improve performance for most installations."
-msgstr ""
-"Du har ikke specificeret en swap-partition. Selv om det ikke er et strengt "
-"krav om dette i alle tilfælle, så vil det øge ydelsen for de fleste "
-"installationer."
-
-#: ../partitions.py:398
-#, python-format
-msgid ""
-"You have specified more than 32 swap devices. The kernel for %s only "
-"supports 32 swap devices."
-msgstr ""
-
-#: ../partitions.py:409
-#, python-format
-msgid ""
-"You have allocated less swap space (%dM) than available RAM (%dM) on your "
-"system. This could negatively impact performance."
-msgstr ""
-"Du har allokeret mindre swap-område (%dM) end tilgængelig RAM (%dM) i dit "
-"system. Dette kan have negativ indvirkning på ydelsen."
-
-#: ../partitions.py:485
-msgid "the partition in use by the installer."
-msgstr "partitionen er i brug af installationsprogrammet."
-
-#: ../partRequests.py:182
-#, python-format
-msgid ""
-"This mount point is invalid. The %s directory must be on the / file system."
-msgstr ""
-"Dette monteringspunkt er ugyldigt. Kataloget %s skal ligge på rodfilsystemet."
-
-#: ../partRequests.py:185
-#, python-format
-msgid ""
-"The mount point %s cannot be used. It must be a symbolic link for proper "
-"system operation. Please select a different mount point."
-msgstr ""
-"Monteringspunktet %s kan ikke bruges. Det skal være et symbolsk link for at "
-"systemet kan fungere korrekt. Vælg et andet monteringspunkt."
-
-#: ../partRequests.py:192
-msgid "This mount point must be on a linux file system."
-msgstr "Dette monteringspunkt skal være på et linux-filsystem."
-
-#: ../partRequests.py:212
-#, python-format
-msgid ""
-"The mount point \"%s\" is already in use, please choose a different mount "
-"point."
-msgstr ""
-"Monteringspunktet \"%s\" er allerede i brug. Vælg venligst et andet "
-"monteringspunkt."
-
-#: ../partRequests.py:226
-#, python-format
-msgid ""
-"The size of the %s partition (%10.2f MB) exceeds the maximum size of %10.2f "
-"MB."
-msgstr ""
-"Størrelsen på %s-partitionen (%10.2f Mb) overskrider maksimal størrelse på %"
-"10.2f Mb."
-
-#: ../partRequests.py:414
-#, python-format
-msgid ""
-"The size of the requested partition (size = %s MB) exceeds the maximum size "
-"of %s MB."
-msgstr ""
-"Størrelsen på forespurgt partition (størrelse = %s MB) overskrider maksimal "
-"størrelse på %s Mb. "
-
-#: ../partRequests.py:419
-#, python-format
-msgid "The size of the requested partition is negative! (size = %s MB)"
-msgstr "Størrelsen på forespurgte partition er negativ! (størrelse = %s Mb)"
-
-#: ../partRequests.py:423
-msgid "Partitions can't start below the first cylinder."
-msgstr "Partitioner kan ikke starte før første cylinder."
-
-#: ../partRequests.py:426
-msgid "Partitions can't end on a negative cylinder."
-msgstr "Partitioner kan ikke slutte på en negativ cylinder."
-
-#: ../tui_bootloader.py:27
-msgid "Which boot loader would you like to use?"
-msgstr "Hvilken boot loader ønsker du at bruge?"
-
-#: ../tui_bootloader.py:37
-msgid "Use GRUB Boot Loader"
-msgstr "Brug GRUB opstartsindlæser"
-
-#: ../tui_bootloader.py:38
-msgid "No Boot Loader"
-msgstr "Ingen boot loader"
-
-#: ../tui_bootloader.py:41 ../tui_bootloader.py:103 ../tui_bootloader.py:161
-#: ../tui_bootloader.py:278 ../tui_bootloader.py:383
-msgid "Boot Loader Configuration"
-msgstr "Konfiguration af boot loader"
-
-#: ../tui_bootloader.py:58
-msgid "Skip Boot Loader"
-msgstr "Overspring boot loader"
-
-#: ../tui_bootloader.py:59
-msgid ""
-"You have elected not to install any boot loader, which is not recommended "
-"unless you have an advanced need. Booting your system into Linux directly "
-"from the hard drive almost always requires a boot loader.\n"
-"\n"
-"Are you sure you want to skip boot loader installation?"
-msgstr ""
-"Du har valgt ikke at installere nogen boot loader, hvilket ikke er "
-"anbefalet, medmindre du har avancerede behov. En boot loader er næsten altid "
-"påkrævet for at genstarte dit system med Linux direkte fra harddisken.\n"
-"\n"
-"Er du sikker på, at du vil springe installationen af boot loaderen over?"
-
-#: ../tui_bootloader.py:88
-msgid ""
-"A few systems need to pass special options to the kernel at boot time to "
-"function properly. If you need to pass boot options to the kernel, enter "
-"them now. If you don't need any or aren't sure, leave this blank."
-msgstr ""
-"Nogle få systemer har brug for angive særlige parametre til kernen under "
-"opstarten for at systemet kan fungere ordentligt. Hvis du har brug for at "
-"overføre opstartsparametre til kernen, så indtast dem nu. Hvis du ikke "
-"behøver det eller er i tvivl, så lad dette felt stå tomt."
-
-#: ../tui_bootloader.py:97
-msgid "Force use of LBA32 (not normally required)"
-msgstr "Tvungen brug af LBA32 (ikke nødvendig normalt)"
-
-#: ../tui_bootloader.py:120
-msgid ""
-"If LBA32 is not supported by your system's BIOS, forcing its use can prevent "
-"your machine from booting.\n"
-"\n"
-"Would you like to continue and force LBA32 mode?"
-msgstr ""
-"Hvis LBA32 ikke er understøttet af BIOS, kan gennemtvingning af brug af "
-"dette forhindre at maskinen starter op.\n"
-"\n"
-"Vil du fortsætte med tvungen brug af LBA32-tilstand?"
-
-#: ../tui_bootloader.py:162
-msgid "Where do you want to install the boot loader?"
-msgstr "Hvor vil du installere boot loaderen?"
-
-#: ../tui_bootloader.py:188 ../tui_bootloader.py:255 ../tui_partition.py:844
-msgid "Device"
-msgstr "Enhed"
-
-#: ../tui_bootloader.py:189 ../tui_bootloader.py:255
-msgid "Boot label"
-msgstr "Opstartsnavn"
-
-#: ../tui_bootloader.py:193
-msgid "Clear"
-msgstr "Ryd"
-
-#: ../tui_bootloader.py:201
-#, fuzzy
-msgid "Edit Boot Label"
-msgstr "ugyldigt opstartsnavn"
-
-#: ../tui_bootloader.py:219 ../tui_bootloader.py:224
-msgid "Invalid Boot Label"
-msgstr "ugyldigt opstartsnavn"
-
-#: ../tui_bootloader.py:220
-msgid "Boot label may not be empty."
-msgstr "Opstartsnavn må ikke være tomt."
-
-#: ../tui_bootloader.py:225
-msgid "Boot label contains illegal characters."
-msgstr "Opstartsnavn indeholder ugyldige tegn."
-
-#: ../tui_bootloader.py:255
-msgid "Default"
-msgstr "Standard"
-
-#: ../tui_bootloader.py:273
-#, python-format
-msgid ""
-"The boot manager %s uses can boot other operating systems as well. Please "
-"tell me what partitions you would like to be able to boot and what label you "
-"want to use for each of them."
-msgstr ""
-"Opstartsprogrammet, som bruges af %s, kan også starte andre "
-"operativsystemer. Angiv hvilke partitioner du gerne vil kunne starte samt "
-"hvilket navn du vil bruge for hvert af dem."
-
-#: ../tui_bootloader.py:286
-msgid ""
-" <Space> select | <F2> select default | <F4> delete | <F12> next screen>"
-msgstr "<Mellemrum> vælg | <F2> vælg standard | <F4> slet | <F12> næste skærm>"
-
-#: ../tui_bootloader.py:335
-msgid "Cannot Delete"
-msgstr "Kan ikke slette"
-
-#: ../tui_bootloader.py:336
-#, python-format
-msgid ""
-"This boot target cannot be deleted because it is for the %s system you are "
-"about to install."
-msgstr ""
-"Dette opstartsmål kan ikke fjernes da det er beregnet til det %s-system du "
-"er ved at installere."
-
-#: ../tui_bootloader.py:378
-msgid ""
-"A boot loader password prevents users from passing arbitrary options to the "
-"kernel. For highest security, you should set a password, but a password is "
-"not necessary for more casual users."
-msgstr ""
-"En adgangskode for boot loaderen hindrer brugere i at give tilfældige "
-"optioner til kernen. For at få højest mulig sikkerhed bør du sætte en "
-"adgangskode, men dette er ikke nødvendig for brugere med mindre krav til "
-"sikkerhed."
-
-#: ../tui_bootloader.py:386
-msgid "Use a GRUB Password"
-msgstr "Brug adgangskode for GRUB"
-
-#: ../tui_bootloader.py:399
-msgid "Boot Loader Password:"
-msgstr "Adgangskode for boot loaderen:"
-
-#: ../tui_bootloader.py:400
-msgid "Confirm:"
-msgstr "Bekræft:"
-
-#: ../tui_bootloader.py:429
-msgid "Passwords Do Not Match"
-msgstr "Adgangskoder er ikke ens."
-
-#: ../tui_bootloader.py:430
-msgid "Passwords do not match"
-msgstr "Adgangskoder er ikke ens."
-
-#: ../tui_bootloader.py:434
-msgid "Password Too Short"
-msgstr "Adgangskoden er for kort."
-
-#: ../tui_bootloader.py:435
-msgid "Boot loader password is too short"
-msgstr "Boot loader adgangskoden er for kort."
-
-#: ../tui_bootloader.py:440
-msgid ""
-"Your boot loader password is shorter than six characters. We recommend a "
-"longer boot loader password.\n"
-"\n"
-"Would you like to continue with this password?"
-msgstr ""
-"Adgangskoden for boot loaderen er kortere end seks tegn. Vi anbefaler en "
-"længere adgangskode for boot loaderen.\n"
-"\n"
-"Vil du fortsætte med denne adgangskode?"
-
-#: ../tui_complete.py:25
-msgid ""
-"Press <Enter> to end the installation process.\n"
-"\n"
-msgstr ""
-"Tryk <enter> for at afslutte installationsprocessen.\n"
-"\n"
-
-#: ../tui_complete.py:26
-msgid "<Enter> to exit"
-msgstr "<Enter> for at afslutte"
-
-#: ../tui_complete.py:30
-#, python-format
-msgid ""
-"Congratulations, your %s installation is complete.\n"
-"\n"
-"%s%s"
-msgstr ""
-"Tillykke, din installation af %s er færdig.\n"
-"\n"
-"%s%s"
-
-#: ../tui_complete.py:33
-#, python-format
-msgid ""
-"For information on errata (updates and bug fixes), visit %s.\n"
-"\n"
-"Information on using your system is available in the %s wiki at %s."
-msgstr ""
-"For information om errata (opdateringer og fejlrettelser), besøg %s.\n"
-"\n"
-"Information om brug af systemet er tilgængelig i %s wiki på %s."
-
-#: ../tui_complete.py:39
-msgid "Complete"
-msgstr "Færdig"
-
-#: ../tui_confirm.py:23
-msgid "Installation to begin"
-msgstr "Installation begynder"
-
-#: ../tui_confirm.py:24
-msgid ""
-"Now, we got all information we need for installation. If there is something "
-"you want change you can still go back. If not choose OK to start."
-msgstr ""
-"Nu har vi alle informationerne vi har brug for installationen. Hvis der er "
-"noget du vil ændre kan du stadigvæk gå tilbage. Hvis ikke så klick OK for at "
-"starte."
-
-#: ../tui_confirm.py:34
-msgid "Reboot?"
-msgstr "Genstart?"
-
-#: ../tui_confirm.py:35
-msgid "The system will be rebooted now."
-msgstr "Systemet vil nu blive genstartet."
-
-#: ../tui_keyboard.py:36
-msgid "Keyboard Selection"
-msgstr "Tastaturvalg"
-
-#: ../tui_keyboard.py:37
-msgid "Which model keyboard is attached to this computer?"
-msgstr "Hvilken tastaturtype er forbundet til denne maskine?"
-
-#: ../tui_language.py:39
-msgid "Language Selection"
-msgstr "Sprogvalg"
-
-#: ../tui_language.py:40
-msgid "What language would you like to use during the installation process?"
-msgstr "Hvilket sprog ønsker du at benytte under installationsprocessen?"
-
-#: ../tui_network.py:39
-#, fuzzy
-msgid "Hostname"
-msgstr "Værtsnavn"
-
-#: ../tui_network.py:42
-msgid ""
-"Please name this computer. The hostname identifies the computer on a "
-"network."
-msgstr ""
-
-#: ../tui_network.py:63 ../tui_network.py:70
-#, fuzzy
-msgid "Invalid Hostname"
-msgstr "ugyldigt opstartsnavn"
-
-#: ../tui_network.py:64
-msgid "You have not specified a hostname."
-msgstr ""
-
-#: ../tui_network.py:71
-#, python-format
-msgid ""
-"The hostname \"%s\" is not valid for the following reason:\n"
-"\n"
-"%s"
-msgstr ""
-
-#: ../tui_partition.py:41
-msgid "Must specify a value"
-msgstr "Værdi skal specificeres"
-
-#: ../tui_partition.py:44
-msgid "Requested value is not an integer"
-msgstr "Forespurgt værdi er ikke et heltal"
-
-#: ../tui_partition.py:46
-msgid "Requested value is too large"
-msgstr "Forespurgt værdi er for stor"
-
-#: ../tui_partition.py:95 ../tui_partition.py:132
-msgid "Free space"
-msgstr "Ledig plads"
-
-#: ../tui_partition.py:97
-msgid "Extended"
-msgstr "Udvidet"
-
-#: ../tui_partition.py:111
-msgid "None"
-msgstr "Intet"
-
-#: ../tui_partition.py:178
-#, python-format
-msgid "Could not allocate requested partitions: %s."
-msgstr "Kunne ikke allokere forespurgte partitioner: %s."
-
-#: ../tui_partition.py:182
-#, python-format
-msgid "Warning: %s"
-msgstr "Advarsel: %s"
-
-#: ../tui_partition.py:183
-msgid "Modify Partition"
-msgstr "Ændre partition"
-
-#: ../tui_partition.py:183
-msgid "Add anyway"
-msgstr "Tilføj alligevel"
-
-#: ../tui_partition.py:201 ../tui_partition.py:203 ../tui_partition.py:205
-#: ../tui_partition.py:230
-msgid "<Not Applicable>"
-msgstr "<Ikke brugbar>"
-
-#: ../tui_partition.py:220
-msgid "Mount Point:"
-msgstr "Monteringspunkt:"
-
-#: ../tui_partition.py:239
-msgid "File System type:"
-msgstr "Filsystemtype:"
-
-#: ../tui_partition.py:270
-msgid "Allowable Drives:"
-msgstr "Tilladte drev:"
-
-#: ../tui_partition.py:292 ../tui_partition.py:371 ../tui_partition.py:419
-msgid "Size (MB):"
-msgstr "Størrelse (Mb):"
-
-#: ../tui_partition.py:324
-msgid "Fixed Size:"
-msgstr "Fast størrelse:"
-
-#: ../tui_partition.py:326
-msgid "Fill maximum size of (MB):"
-msgstr "Fyld maksimal størrelse på (Mb):"
-
-#: ../tui_partition.py:330
-msgid "Fill all available space:"
-msgstr "Fyld al tilgængelig plads:"
-
-#: ../tui_partition.py:351
-msgid "Start Cylinder:"
-msgstr "Startcylinder:"
-
-#: ../tui_partition.py:364
-msgid "End Cylinder:"
-msgstr "Slutcylinder:"
-
-#: ../tui_partition.py:386
-msgid "Number of spares?"
-msgstr "Antal reservediske?"
-
-#: ../tui_partition.py:400
-msgid "File System Type:"
-msgstr "Filsystemtype:"
-
-#: ../tui_partition.py:413
-msgid "File System Label:"
-msgstr "Filsystemetiket:"
-
-#: ../tui_partition.py:424
-msgid "File System Option:"
-msgstr "Alternativ for filsystem:"
-
-#: ../tui_partition.py:427 ../tui_partition.py:652
-#, python-format
-msgid "Format as %s"
-msgstr "Formatér som %s"
-
-#: ../tui_partition.py:429 ../tui_partition.py:654
-#, python-format
-msgid "Migrate to %s"
-msgstr "Migrér til %s"
-
-#: ../tui_partition.py:431 ../tui_partition.py:656
-msgid "Leave unchanged"
-msgstr "Forlad uforandret"
-
-#: ../tui_partition.py:446 ../tui_partition.py:629
-msgid "File System Options"
-msgstr "Filsystemsvalgmuligheder"
-
-#: ../tui_partition.py:449
-msgid ""
-"Please choose how you would like to prepare the file system on this "
-"partition."
-msgstr ""
-"Venligst vælg hvordan du ønsker at forberede filsystemet på denne partition."
-
-#: ../tui_partition.py:457 ../tui_partition.py:607
-msgid "Check for bad blocks"
-msgstr "Se efter beskadigede blokke"
-
-#: ../tui_partition.py:461
-msgid "Leave unchanged (preserve data)"
-msgstr "Forlad uforandret (behold data)"
-
-#: ../tui_partition.py:470
-msgid "Format as:"
-msgstr "Formatér som:"
-
-#: ../tui_partition.py:489
-msgid "Migrate to:"
-msgstr "Migrér til:"
-
-#: ../tui_partition.py:559
-msgid "Add Partition"
-msgstr "Tilføj partition"
-
-#: ../tui_partition.py:601
-msgid "Force to be a primary partition"
-msgstr "Tving til at være en primærpartition"
-
-#: ../tui_partition.py:684 ../tui_partition.py:738
-msgid "Invalid Entry for Partition Size"
-msgstr "Ugyldig værdi for partitionsstørrelse"
-
-#: ../tui_partition.py:696
-msgid "Invalid Entry for Maximum Size"
-msgstr "Ugyldig opføring for maksimum størrelse"
-
-#: ../tui_partition.py:716
-msgid "Invalid Entry for Starting Cylinder"
-msgstr "Ugyldig værdi for startcylinder"
-
-#: ../tui_partition.py:730
-msgid "Invalid Entry for End Cylinder"
-msgstr "Ugyldig værdi for slutcylinder"
-
-#: ../tui_partition.py:748 ../tui_partition.py:769
-msgid "Error With Request"
-msgstr "Fejl med forespørgsel"
-
-#: ../tui_partition.py:838
-msgid "Partitioning"
-msgstr "Partitionering"
-
-#: ../tui_partition.py:844
-msgid "Start"
-msgstr "Start"
-
-#: ../tui_partition.py:844
-msgid "End"
-msgstr "Slut"
-
-#: ../tui_partition.py:844
-msgid "Size"
-msgstr "Størrelse"
-
-#: ../tui_partition.py:844
-msgid "Type"
-msgstr "Type"
-
-#: ../tui_partition.py:844
-msgid "Mount Point"
-msgstr "Monteringspunkt"
-
-#: ../tui_partition.py:848
-msgid "New"
-msgstr "Ny"
-
-#: ../tui_partition.py:850
-msgid "Delete"
-msgstr "Slet"
-
-#: ../tui_partition.py:853
-msgid ""
-" F1-Help F2-New F3-Edit F4-Delete F5-Reset F12-OK "
-msgstr ""
-" F1-Hjælp F2-Ny F3-Redigér F4-Fjern F5-Nulstil F12-O.k. "
-
-#: ../tui_partition.py:883
-msgid "No Root Partition"
-msgstr "Ingen rodpartition"
-
-#: ../tui_partition.py:884
-msgid "Installation requires a / partition."
-msgstr "Installationen kræver en / partition."
-
-#: ../tui_partition.py:923
-msgid "Partitioning Type"
-msgstr "Partitionstype"
-
-#: ../tui_partition.py:925
-msgid ""
-"Installation requires partitioning of your hard drive. The default layout "
-"is reasonable for most users. You can either choose to use this or create "
-"your own."
-msgstr ""
-"Installation kræver partitionering af din disk. Standard-opdelingen er "
-"fornuftig for de fleste brugere. Du kan enten vælge denne, eller lave din "
-"egen opdeling. "
-
-#: ../tui_partition.py:932
-msgid "Remove all partitions on selected drives and create default layout"
-msgstr ""
-"Fjern alle partitioner på valgte partitioner og opret standardudlægning"
-
-#: ../tui_partition.py:933
-msgid "Create custom layout"
-msgstr "Opret selvdefineret layout"
-
-#: ../tui_partition.py:947
-msgid "Which drive(s) do you want to use for this installation?"
-msgstr "Hvilke drev vil du bruge til denne installation?"
-
-#: ../tui_partition.py:960
-msgid "<Space>,<+>,<-> selection | <F2> Add drive | <F12> next screen"
-msgstr ""
-"<Mellemrum>,<+>,<-> valg | <F1> Tilføj drev | <F12> næste skærm"
-
-#: ../tui_partition.py:1029
-msgid "Review Partition Layout"
-msgstr "Vis igen de partitioner som oprettes"
-
-#: ../tui_partition.py:1030
-msgid "Review and modify partitioning layout?"
-msgstr "Vis igen (og ændr om det behøves) de partitioner som oprettes?"
-
-#: ../tui_progress.py:52
-msgid "File Installation"
-msgstr "Fil-installation"
-
-#: ../tui.py:118
-msgid "Exception Occurred"
-msgstr "Undtagelse hændte"
-
-#: ../tui.py:189
-msgid "Error!"
-msgstr "Fejl!"
-
-#: ../tui.py:190
-#, python-format
-msgid ""
-"An error occurred when attempting to load an pomona interface component.\n"
-"\n"
-"className = %s\n"
-"\n"
-"Error: %s"
-msgstr ""
-"Et fejl skete ved forsøg at indlæse en pomona interface komponent.\n"
-"\n"
-"className = %s\n"
-"\n"
-"Error: %s"
-
-#: ../tui.py:195 ../tui.py:197
-msgid "Exit"
-msgstr "Afslut"
-
-#: ../tui.py:195 ../tui.py:391
-msgid "Retry"
-msgstr "Prøv igen"
-
-#: ../tui.py:220
-msgid "Cancelled"
-msgstr "Annulleret"
-
-#: ../tui.py:221
-msgid "I can't go to the previous step from here. You will have to try again."
-msgstr "Jeg kan ikke gå til forrige trin herfra. Du skal prøve igen."
-
-#: ../tui.py:235
-#, python-format
-msgid "Welcome to %s"
-msgstr "Velkommen til %s"
-
-#: ../tui.py:238
-msgid ""
-" <F1> for help | <Tab> between elements | <Space> selects | <F12> next screen"
-msgstr ""
-" <F1> for hjælp | <Tab> imellem punkter | <Mellemrum> vælg | <F12> næste side"
-
-#: ../tui.py:240
-msgid ""
-" <Tab>/<Alt-Tab> between elements | <Space> selects | <F12> next "
-"screen"
-msgstr ""
-" <Tab>/<Alt-Tab> imellem punkter | <Mellemrum> vælger | <F12> næste side"
-
-#: ../tui.py:285
-msgid "Help not available"
-msgstr "Ingen hjælp tilgængelig"
-
-#: ../tui.py:286
-msgid "No help is available for this step of the install."
-msgstr "Ingen hjælp er tilgængelig for dette trin af installationen."
-
-#: ../tui.py:387
-msgid "Fix"
-msgstr "Reparér"
-
-#: ../tui.py:392
-msgid "Ignore"
-msgstr "Ignorér"
-
-#: ../tui_timezone.py:63
-msgid "In which time zone are you located?"
-msgstr "Hvilken tidszone befinder du dig i?"
-
-#: ../tui_timezone.py:78
-msgid "System clock uses UTC"
-msgstr "System-ur bruger UTC"
-
-#: ../tui_timezone.py:81
-msgid "Time Zone Selection"
-msgstr "Tidszone valg"
-
-#: ../tui_userauth.py:29
-msgid "Root Password"
-msgstr "'root'-adgangskode"
-
-#: ../tui_userauth.py:31
-#, fuzzy
-msgid ""
-"Pick a root password. You must type it twice to ensure you know it and do "
-"not make a typing mistake. Remember that the root password isa critical part "
-"of system security!"
-msgstr ""
-"Vælg en 'root'-adgangskode. Du skal skrive den to gange for at sikre at du "
-"ved hvad det er og ikke får tastet forkert. Husk at 'root'-adgangskoden er "
-"en afgørende del af systemets sikkerhed!"
-
-#: ../tui_userauth.py:41
-msgid "Password:"
-msgstr "Adgangskode:"
-
-#: ../tui_userauth.py:42
-msgid "Password (confirm):"
-msgstr "Adgangskode (bekræft):"
-
-#: ../tui_userauth.py:59
-msgid "Password Length"
-msgstr "Adgangskodelængde"
-
-#: ../tui_userauth.py:60
-msgid "The root password must be at least 6 characters long."
-msgstr "'root'-adgangskoden skal være på mindst 6 tegn."
-
-#: ../tui_userauth.py:63
-msgid "Password Mismatch"
-msgstr "Adgangskode stemmer ikke"
-
-#: ../tui_userauth.py:64
-msgid "The passwords you entered were different. Please try again."
-msgstr "De to adgangskoder du indtastede var ikke ens. Prøv igen."
-
-#: ../tui_userauth.py:67
-msgid "Error with Password"
-msgstr "Fejl med adgangskode"
-
-#: ../tui_userauth.py:68
-msgid ""
-"Requested password contains non-ASCII characters, which are not allowed."
-msgstr ""
-"Den udbedte adgangskode indeholder ikke-ascii tegn som ikke er tilladt."
-
-#: ../tui_welcome.py:12
-#, python-format
-msgid "%s"
-msgstr "%s"
-
-#: ../tui_welcome.py:13
-#, python-format
-msgid ""
-"Welcome to %s!\n"
-"\n"
-msgstr ""
-"Velkommen til %s!\n"
-"\n"
-
-#. generated from lang-table
-msgid "English"
-msgstr "Engelsk"
-
-#. generated from lang-table
-msgid "German"
-msgstr "Tysk"
-
-#. generated from lang-table
-msgid "Danish"
-msgstr "Dansk"
-
-#~ msgid "Checking for Bad Blocks"
-#~ msgstr "Kontrollerer for dårlige blokke"
-
-#~ msgid ""
-#~ "An error occurred unmounting the disc. Please make sure you're not "
-#~ "accessing the disk from the shell on tty2 and then click OK to retry."
-#~ msgstr ""
-#~ "En fejl skete ved afmontering af cd-en. Forsikr dig venligst om at du "
-#~ "ikke bruger %s fra skallen, og klik så O.k. for at prøve igen."
-
-#~ msgid ""
-#~ "The file %s cannot be opened. This is due to a missing file or perhaps a "
-#~ "corrupt package. Please verify your installation images and that you "
-#~ "have all the required media.\n"
-#~ "\n"
-#~ "If you reboot, your system will be left in an inconsistent state that "
-#~ "will likely require reinstallation.\n"
-#~ "\n"
-#~ msgstr ""
-#~ "Filen %s kan ikke åbnes. Dette beror på en manglende fil eller måske en "
-#~ "beskadiget pakke. Kontrollér dine installationsmedier og at du har alle "
-#~ "de nødvendige medier.\n"
-#~ "\n"
-#~ "Hvis du genstarter vil dit system være i en inkonsistent tilstand, som "
-#~ "sandsynligvis vil kræve geninstallation.\n"
-#~ "\n"
-
-#, fuzzy
-#~ msgid "Probing CDROM"
-#~ msgstr "Forkert cd-rom"
-
-#~ msgid "Searching for a valid disc on /dev/%s..."
-#~ msgstr "Kontrollerer for dårlige blokke på /dev/%s..."
-
-#~ msgid "Wrong CDROM"
-#~ msgstr "Forkert cd-rom"
-
-#~ msgid "That's not the correct %s CDROM in /dev/%s."
-#~ msgstr "Dette er ikke den korrekte %s-cd-rom på /dev/%s."
-
-#~ msgid "Insert CDROM"
-#~ msgstr "skift cd-rom"
-
-#~ msgid "Please insert the %s disc to continue."
-#~ msgstr "Indsæt venligst %s disk for at fortsætte."
-
-#~ msgid "Install on System"
-#~ msgstr "Installér på system"
-
-#~ msgid "IPFire"
-#~ msgstr "IPFire"
-
-#~ msgid "Disk Partitioning Setup"
-#~ msgstr "Opsætning af diskpartitioner"
-
-#~ msgid "Autopartition"
-#~ msgstr "Auto-partition"
-
-#~ msgid "Disk Druid"
-#~ msgstr "Diskdruid"
-
-#~ msgid "Missing ISO 9660 Image"
-#~ msgstr "Mangler ISO 9660-image"
-
-#~ msgid ""
-#~ "The installer has tried to mount image #%s, but cannot find it on the "
-#~ "hard drive.\n"
-#~ "\n"
-#~ "Please copy this image to the drive and click Retry. Click Reboot to "
-#~ "abort the installation."
-#~ msgstr ""
-#~ "Installeringsprogrammet har forsøgt at montere image #%s, men kan ikke "
-#~ "finde det på disken.\n"
-#~ "\n"
-#~ "Kopiér venligst dette image til drevet og klik forsøg igen. Klik genstart "
-#~ "for at afbryde installationen."
-
-#~ msgid "Re_try"
-#~ msgstr "_Prøv igen"
-
-#~ msgid "Couldn't Mount ISO Source"
-#~ msgstr "Kunne ikke montere ISO-kilde"
-
-#~ msgid ""
-#~ "An error occurred mounting the source device %s. This may happen if your "
-#~ "ISO images are located on an advanced storage device like LVM or RAID, or "
-#~ "if there was a problem mounting a partition. Click reboot to abort the "
-#~ "installation."
-#~ msgstr ""
-#~ "Der skete en fejl ved montering af kildeenheden %s. Dette kan ske hvis "
-#~ "dine ISO-image ligger på et avancerede lagringsmedier som LVM eller RAID, "
-#~ "eller hvis der var et problem med at montere en partition. Klik genstart "
-#~ "for at afbryde installationen. "
-
-#~ msgid "Source Type"
-#~ msgstr "Kildetype:"
-
-#~ msgid ""
-#~ "In installation you have to choose a source for the installation files. "
-#~ "Mostly you will choose the disc here, but you are also able to install by "
-#~ "HTTP, FTP hard disk or usb-key."
-#~ msgstr ""
-#~ "I installationen skal du vælge en kilde for installationsfilerne. Typisk "
-#~ "vil du vælge en harddisk, men du vil også kunne installere fra HTTP, FTP "
-#~ "harddisk eller usb-nøgle."
-
-#~ msgid "Install Disc"
-#~ msgstr "Installationsdisk"
-
-#~ msgid "Internet Source"
-#~ msgstr "Internet kilde"
-
-#~ msgid "External Drive"
-#~ msgstr "Eksternt drev"
-
-#~ msgid "No CDROM found"
-#~ msgstr "Ingen Cd fundet"
-
-#~ msgid ""
-#~ "You choosed to install from an installtion disc, but there was no cdrom "
-#~ "drive found on the system. Please choose another installation method."
-#~ msgstr ""
-#~ "Du valgte at installere fra installations-disken, men der blev ikke "
-#~ "fundet noget cdrom-drev på dette system. Vælg en anden "
-#~ "installationsmethode."
-
-#~ msgid "Source URL"
-#~ msgstr "Kilde URL:"
-
-#~ msgid ""
-#~ "Enter a host you get the files from.You also must enter a path where the "
-#~ "installer finds the files in."
-#~ msgstr ""
-#~ "Angiv en host som du modtager filerne fra. Du skal også angive en sti "
-#~ "hvor instalationsprogrammet kan finde filerne."
-
-#~ msgid "Path:"
-#~ msgstr "Sti:"
-
-#~ msgid "Wrong Protocol"
-#~ msgstr "Forkert protokol"
-
-#~ msgid ""
-#~ "You entered a protocol that is not supported by Pomona. There are only "
-#~ "http:// and ftp:// available."
-#~ msgstr ""
-#~ "Du har angivet et protokol som ikke er understøttet af Pomona. Der står "
-#~ "kun http:// og ftp:// til rådighed."
-
-#~ msgid "Syntax Error"
-#~ msgstr "Syntaksfejl"
-
-#~ msgid "The path of the URL must end with a /."
-#~ msgstr "Stien af denne URL skal afslutte med et /."
-
-#~ msgid ""
-#~ "When we tested your given URL there was an error.\n"
-#~ "\n"
-#~ "%s"
-#~ msgstr ""
-#~ "Der opstod en fejl da vi testede din angivne URL.\n"
-#~ "\n"
-#~ "%s"
-
-#~ msgid "Downloading"
-#~ msgstr "Indlæser"
-
-#~ msgid "Connecting..."
-#~ msgstr "Tilslutter..."
-
-#~ msgid "Retrieving %s"
-#~ msgstr "Modtager %s"
-
-#~ msgid ""
-#~ "The file %s cannot be opened. This is due to a missing file or perhaps a "
-#~ "corrupt package. Please verify your mirror contains all required "
-#~ "packages, and try using a different one.\n"
-#~ "\n"
-#~ "If you reboot, your system will be left in an inconsistent state that "
-#~ "will likely require reinstallation.\n"
-#~ "\n"
-#~ msgstr ""
-#~ "Filen %s kan ikke åbnes. Dette beror på en manglende fil eller måske en "
-#~ "beskadiget pakke. Kontrollér at din mirror indeholder alle de nødvendige "
-#~ "pakker, eller prøv at bruge en anden mirror.\n"
-#~ "\n"
-#~ "Hvis du genstarter vil dit system være i en inkonsistent tilstand, som "
-#~ "sandsynligvis vil kræve geninstallation.\n"
-#~ "\n"
-
-#~ msgid ""
-#~ "An error occurred unmounting the disc. Please make sure you're not "
-#~ "accessing %s from the shell on tty2 and then click OK to retry."
-#~ msgstr ""
-#~ "En fejl skete ved afmontering af cd-en. Forsikr dig venligst om at du "
-#~ "ikke bruger %s fra skallen, og klik så O.k. for at prøve igen."
+++ /dev/null
-# German translation of Pomona
-# Copyright (C) 2007 The IPFire Team
-# This file is distributed under the same license as IPFire.
-# Michael Tremer <michael.tremer@ipfire.org>, 2007.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: Pomona\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-01-29 01:02+0100\n"
-"PO-Revision-Date: 2009-01-29 01:26+0100\n"
-"Last-Translator: Michael Tremer <michael.tremer@ipfire.org>\n"
-"Language-Team: German\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-#: ../autopart.py:751
-#, python-format
-msgid ""
-"Could not allocate cylinder-based partitions as primary partitions.\n"
-"\n"
-"%s"
-msgstr ""
-
-#: ../autopart.py:756
-#, python-format
-msgid ""
-"Could not allocate partitions as primary partitions.\n"
-"\n"
-"%s"
-msgstr ""
-
-#: ../autopart.py:761
-#, python-format
-msgid ""
-"Could not allocate cylinder-based partitions.\n"
-"\n"
-"%s"
-msgstr ""
-
-#: ../autopart.py:800
-#, python-format
-msgid ""
-"Boot partition %s doesn't belong to a BSD disk label. SRM won't be able to "
-"boot from this partition. Use a partition belonging to a BSD disk label or "
-"change this device disk label to BSD."
-msgstr ""
-
-#: ../autopart.py:802
-#, python-format
-msgid ""
-"Boot partition %s doesn't belong to a disk with enough free space at its "
-"beginning for the bootloader to live on. Make sure that there's at least 5MB "
-"of free space at the beginning of the disk that contains /boot"
-msgstr ""
-
-#: ../autopart.py:804
-#, python-format
-msgid ""
-"Boot partition %s isn't a VFAT partition. EFI won't be able to boot from "
-"this partition."
-msgstr ""
-
-#: ../autopart.py:806
-msgid ""
-"The boot partition must entirely be in the first 4GB of the disk. "
-"OpenFirmware won't be able to boot this installation."
-msgstr ""
-
-#: ../autopart.py:813
-#, python-format
-msgid ""
-"Boot partition %s may not meet booting constraints for your architecture."
-msgstr ""
-
-#: ../autopart.py:951
-msgid "Requested Partition Does Not Exist"
-msgstr "Die angegebene Partition existiert nicht"
-
-#: ../autopart.py:952
-#, python-format
-msgid ""
-"Unable to locate partition %s to use for %s.\n"
-"\n"
-"Press 'OK' to reboot your system."
-msgstr ""
-
-#: ../autopart.py:997 ../autopart.py:1029
-msgid "Automatic Partitioning Errors"
-msgstr ""
-
-#: ../autopart.py:998
-#, python-format
-msgid ""
-"The following errors occurred with your partitioning:\n"
-"\n"
-"%s\n"
-"\n"
-"Press 'OK' to reboot your system."
-msgstr ""
-
-#: ../autopart.py:1007
-msgid "Warnings During Automatic Partitioning"
-msgstr ""
-
-#: ../autopart.py:1008
-#, python-format
-msgid ""
-"Following warnings occurred during automatic partitioning:\n"
-"\n"
-"%s"
-msgstr ""
-
-#: ../autopart.py:1016 ../tui_partition.py:177
-msgid "Error Partitioning"
-msgstr "Partitionierungsfehler"
-
-#: ../autopart.py:1017
-#, python-format
-msgid ""
-"Could not allocate requested partitions: \n"
-"\n"
-"%s."
-msgstr ""
-
-#: ../autopart.py:1027
-msgid ""
-"\n"
-"\n"
-"Press 'OK' to choose a different partitioning option."
-msgstr ""
-"\n"
-"\n"
-"Drücken Sie 'OK' um eine andere Partitionierungsoption zu wählen."
-
-#: ../autopart.py:1030
-#, python-format
-msgid ""
-"The following errors occurred with your partitioning:\n"
-"\n"
-"%s\n"
-"\n"
-"This can happen if there is not enough space on your hard drive(s) for the "
-"installation. %s"
-msgstr ""
-
-#: ../autopart.py:1105 ../bootloader.py:745 ../partedUtils.py:230
-#: ../partedUtils.py:531 ../partedUtils.py:568 ../tui_bootloader.py:119
-#: ../tui_bootloader.py:439 ../tui_partition.py:182
-msgid "Warning"
-msgstr "Warnung"
-
-#: ../autopart.py:1126
-msgid ""
-"Automatic Partitioning sets partitions based on the selected installation "
-"type. You also can customize the partitions once they have been created.\n"
-"\n"
-"The manual disk partitioning tool, Disk Druid, allows you to create "
-"partitions in an interactive environment. You can set the file system types, "
-"mount points, partition sizes, and more."
-msgstr ""
-
-#: ../autopart.py:1137
-msgid ""
-"Before automatic partitioning can be set up by the installation program, you "
-"must choose how to use the space on your hard drives."
-msgstr ""
-
-#: ../autopart.py:1142
-msgid "Remove all partitions on this system"
-msgstr "Entferne alle Partitionen auf diesem System"
-
-#: ../autopart.py:1144
-#, python-format
-msgid ""
-"You have chosen to remove all partitions (ALL DATA) on the following drives:%"
-"s\n"
-"Are you sure you want to do this?"
-msgstr ""
-"Sie haben sich entschlossen alle Partitionen (einschließlich aller Daten) "
-"auf den folgenden Datenträgern zu entfernen: %s\n"
-"Sind Sie sich sicher?"
-
-#: ../bootloader.py:696
-msgid "Bootloader"
-msgstr "Bootloader"
-
-#: ../bootloader.py:696
-msgid "Installing bootloader..."
-msgstr "Installiere Bootloader..."
-
-#: ../bootloader.py:746
-msgid ""
-"No kernel packages were installed on your system. Your boot loader "
-"configuration will not be changed."
-msgstr ""
-
-#: ../constants.py:41
-#, python-format
-msgid ""
-"An unhandled exception has occurred. This is most likely a bug. Please "
-"save a copy of the detailed exception and file a bug report against pomona "
-"at %s"
-msgstr ""
-"Ein unerwarteter Fehler ist aufgetreten. Meistens handelt es sich um einen "
-"Bug, wenn Sie diese Meldung sehen. Bitte sichern Sie eine detaillierte Kopie "
-"dieses Fehlers und senden Sie diese an den Bugtracker %s."
-
-#: ../constants.py:83 ../installer.py:93 ../tui_confirm.py:28
-#: ../tui_network.py:65 ../tui_network.py:74 ../tui.py:224 ../tui.py:390
-msgid "OK"
-msgstr "OK"
-
-#: ../constants.py:87 ../partIntfHelpers.py:150 ../partIntfHelpers.py:392
-#: ../tui_bootloader.py:194 ../tui.py:103 ../tui.py:104 ../tui.py:393
-msgid "Cancel"
-msgstr "Abbrechen"
-
-#: ../constants.py:91 ../tui_confirm.py:28 ../tui_confirm.py:30
-msgid "Back"
-msgstr "Zurück"
-
-#: ../constants.py:95 ../tui_bootloader.py:67 ../tui.py:388
-msgid "Yes"
-msgstr "Ja"
-
-#: ../constants.py:99 ../tui_bootloader.py:67 ../tui.py:389
-msgid "No"
-msgstr "Nein"
-
-#: ../constants.py:103 ../tui_bootloader.py:270 ../tui_partition.py:849
-msgid "Edit"
-msgstr "Bearbeiten"
-
-#: ../fsset.py:422
-msgid "Checking"
-msgstr "Überprüfe"
-
-#: ../fsset.py:423
-#, python-format
-msgid "Checking filesystem on %s..."
-msgstr "Untersuche Dateisystem %s..."
-
-#: ../fsset.py:434
-msgid "Resizing"
-msgstr ""
-
-#: ../fsset.py:435
-#, python-format
-msgid "Resizing filesystem on %s..."
-msgstr "Verändere Dateisystemgröße auf %s..."
-
-#: ../fsset.py:578 ../fsset.py:1112 ../fsset.py:1143 ../fsset.py:1205
-#: ../fsset.py:1216 ../fsset.py:1270 ../fsset.py:1281 ../fsset.py:1303
-#: ../fsset.py:1352 ../fsset.py:1433 ../partIntfHelpers.py:289
-msgid "Error"
-msgstr "Fehler"
-
-#: ../fsset.py:579
-#, python-format
-msgid ""
-"An error occurred migrating %s to ext3. It is possible to continue without "
-"migrating this file system if desired.\n"
-"\n"
-"Would you like to continue without migrating %s?"
-msgstr ""
-"Bei der Migration von %s zu ext3 trat ein Fehler auf. Es ist möglich "
-"fortzufahren ohne die Migration zu vollziehen.\n"
-"\n"
-"Möchten Sie ohne Migration von %s fortfahren?"
-
-#: ../fsset.py:1046
-msgid "First sector of boot partition"
-msgstr "Erster Sektor der Boot-Partition"
-
-#: ../fsset.py:1047
-msgid "Master Boot Record (MBR)"
-msgstr "Boot-Sektor (MBR)"
-
-#: ../fsset.py:1113
-#, python-format
-msgid ""
-"An error occurred trying to initialize swap on device %s. This problem is "
-"serious, and the install cannot continue.\n"
-"\n"
-"Press <Enter> to reboot your system."
-msgstr ""
-
-#: ../fsset.py:1142
-msgid "Skip"
-msgstr "Ãœberspringen"
-
-#: ../fsset.py:1142 ../tui_complete.py:40
-msgid "Reboot"
-msgstr "Neustarten"
-
-#: ../fsset.py:1163
-#, python-format
-msgid ""
-"The swap device:\n"
-"\n"
-" /dev/%s\n"
-"\n"
-"is a version 0 Linux swap partition. If you want to use this device, you "
-"must reformat as a version 1 Linux swap partition. If you skip it, the "
-"installer will ignore it during the installation."
-msgstr ""
-
-#: ../fsset.py:1170
-msgid "Reformat"
-msgstr "Neu formatieren"
-
-#: ../fsset.py:1174
-#, python-format
-msgid ""
-"The swap device:\n"
-"\n"
-" /dev/%s\n"
-"\n"
-"in your /etc/fstab file is currently in use as a software suspend partition, "
-"which means your system is hibernating. To perform an upgrade, please shut "
-"down your system rather than hibernating it."
-msgstr ""
-
-#: ../fsset.py:1182
-#, python-format
-msgid ""
-"The swap device:\n"
-"\n"
-" /dev/%s\n"
-"\n"
-"in your /etc/fstab file is currently in use as a software suspend partition, "
-"which means your system is hibernating. If you are performing a new install, "
-"make sure the installer is set to format all swap partitions."
-msgstr ""
-
-#: ../fsset.py:1192
-msgid ""
-"\n"
-"\n"
-"Choose Skip if you want the installer to ignore this partition during the "
-"upgrade. Choose Format to reformat the partition as swap space. Choose "
-"Reboot to restart the system."
-msgstr ""
-
-#: ../fsset.py:1198
-msgid "Format"
-msgstr "Formatieren"
-
-#: ../fsset.py:1206
-#, python-format
-msgid ""
-"Error enabling swap device %s: %s\n"
-"\n"
-"The /etc/fstab on your upgrade partition does not reference a valid swap "
-"partition.\n"
-"\n"
-"Press OK to reboot your system."
-msgstr ""
-
-#: ../fsset.py:1217
-#, python-format
-msgid ""
-"Error enabling swap device %s: %s\n"
-"\n"
-"This most likely means this swap partition has not been initialized.\n"
-"\n"
-"Press OK to reboot your system."
-msgstr ""
-
-#: ../fsset.py:1271
-#, python-format
-msgid ""
-"Bad blocks have been detected on device /dev/%s. We do not recommend you use "
-"this device.\n"
-"\n"
-"Press <Enter> to reboot your system"
-msgstr ""
-
-#: ../fsset.py:1282
-#, python-format
-msgid ""
-"An error occurred searching for bad blocks on %s. This problem is serious, "
-"and the install cannot continue.\n"
-"\n"
-"Press <Enter> to reboot your system."
-msgstr ""
-
-#: ../fsset.py:1304
-#, python-format
-msgid ""
-"An error occurred trying to format %s. This problem is serious, and the "
-"install cannot continue.\n"
-"\n"
-"Press <Enter> to reboot your system."
-msgstr ""
-
-#: ../fsset.py:1353
-#, python-format
-msgid ""
-"An error occurred trying to migrate %s. This problem is serious, and the "
-"install cannot continue.\n"
-"\n"
-"Press <Enter> to reboot your system."
-msgstr ""
-
-#: ../fsset.py:1380 ../fsset.py:1389
-msgid "Invalid mount point"
-msgstr "Ungültiger Mount-Point"
-
-#: ../fsset.py:1381
-#, python-format
-msgid ""
-"An error occurred when trying to create %s. Some element of this path is "
-"not a directory. This is a fatal error and the install cannot continue.\n"
-"\n"
-"Press <Enter> to reboot your system."
-msgstr ""
-
-#: ../fsset.py:1390
-#, python-format
-msgid ""
-"An error occurred when trying to create %s: %s. This is a fatal error and "
-"the install cannot continue.\n"
-"\n"
-"Press <Enter> to reboot your system."
-msgstr ""
-
-#: ../fsset.py:1403
-msgid "Unable to mount filesystem"
-msgstr "Konnte das Dateisystem nicht mounten"
-
-#: ../fsset.py:1404
-#, python-format
-msgid ""
-"An error occurred mounting device %s as %s. You may continue installation, "
-"but there may be problems."
-msgstr ""
-
-#: ../fsset.py:1411 ../fsset.py:1820 ../fsset.py:1827 ../packages.py:131
-#: ../partedUtils.py:578 ../tui_confirm.py:37
-msgid "_Reboot"
-msgstr "_Neustart"
-
-#: ../fsset.py:1411 ../partedUtils.py:578
-msgid "_Continue"
-msgstr "_Fortfahren"
-
-#: ../fsset.py:1419
-#, python-format
-msgid ""
-"Error mounting device %s as %s: %s\n"
-"\n"
-"Devices in /etc/fstab should be specified by label, not by device name.\n"
-"\n"
-"Press OK to reboot your system."
-msgstr ""
-
-#: ../fsset.py:1426
-#, python-format
-msgid ""
-"Error mounting device %s as %s: %s\n"
-"\n"
-"This most likely means this partition has not been formatted.\n"
-"\n"
-"Press OK to reboot your system."
-msgstr ""
-
-#: ../fsset.py:1812
-msgid "Duplicate Labels"
-msgstr "Doppelte Labels"
-
-#: ../fsset.py:1813
-#, python-format
-msgid ""
-"Multiple devices on your system are labelled %s. Labels across devices must "
-"be unique for your system to function properly.\n"
-"\n"
-"Please fix this problem and restart the installation process."
-msgstr ""
-
-#: ../fsset.py:1822
-msgid "Invalid Label"
-msgstr "Ungültiges Label"
-
-#: ../fsset.py:1823
-#, python-format
-msgid ""
-"An invalid label was found on device %s. Please fix this problem and "
-"restart the installation process."
-msgstr ""
-
-#: ../fsset.py:2049
-msgid "Formatting"
-msgstr "Formatiere"
-
-#: ../fsset.py:2050
-#, python-format
-msgid "Formatting %s file system..."
-msgstr "Formatiere %s..."
-
-#: ../installer.py:88
-msgid "Fatal Error"
-msgstr "Fehler"
-
-#: ../installer.py:89
-#, python-format
-msgid ""
-"You do not have enough RAM to install %s on this machine.\n"
-"\n"
-"Press <return> to reboot your system.\n"
-msgstr ""
-"Sie haben nicht genug Arbeitsspeicher um %s auf diesem System zu "
-"installieren.\n"
-"\n"
-"Drücken Sie <Neustart> um das System neu zu starten.\n"
-
-#: ../installer.py:173
-msgid "Starting text installation..."
-msgstr "Starte Textinstallation..."
-
-#: ../keyboard_models.py:48
-msgid "keyboard|Arabic (azerty)"
-msgstr ""
-
-#: ../keyboard_models.py:51
-msgid "keyboard|Arabic (azerty/digits)"
-msgstr ""
-
-#: ../keyboard_models.py:54
-msgid "keyboard|Arabic (digits)"
-msgstr ""
-
-#: ../keyboard_models.py:57
-msgid "keyboard|Arabic (qwerty)"
-msgstr ""
-
-#: ../keyboard_models.py:60
-msgid "keyboard|Arabic (qwerty/digits)"
-msgstr ""
-
-#: ../keyboard_models.py:63
-msgid "keyboard|Belgian (be-latin1)"
-msgstr ""
-
-#: ../keyboard_models.py:66
-msgid "keyboard|Bengali (Inscript)"
-msgstr ""
-
-#: ../keyboard_models.py:69
-msgid "keyboard|Bengali (Probhat)"
-msgstr ""
-
-#: ../keyboard_models.py:72
-msgid "keyboard|Bulgarian"
-msgstr ""
-
-#: ../keyboard_models.py:75
-msgid "keyboard|Bulgarian (Phonetic)"
-msgstr ""
-
-#: ../keyboard_models.py:78
-msgid "keyboard|Brazilian (ABNT2)"
-msgstr ""
-
-#: ../keyboard_models.py:81
-msgid "keyboard|French Canadian"
-msgstr ""
-
-#: ../keyboard_models.py:84
-msgid "keyboard|Croatian"
-msgstr ""
-
-#: ../keyboard_models.py:87
-msgid "keyboard|Czech"
-msgstr ""
-
-#: ../keyboard_models.py:90
-msgid "keyboard|Czech (qwerty)"
-msgstr ""
-
-#: ../keyboard_models.py:93
-msgid "keyboard|German"
-msgstr ""
-
-#: ../keyboard_models.py:96
-msgid "keyboard|German (latin1)"
-msgstr ""
-
-#: ../keyboard_models.py:99
-msgid "keyboard|German (latin1 w/ no deadkeys)"
-msgstr ""
-
-#: ../keyboard_models.py:102
-msgid "keyboard|Devanagari (Inscript)"
-msgstr ""
-
-#: ../keyboard_models.py:105
-msgid "keyboard|Dvorak"
-msgstr ""
-
-#: ../keyboard_models.py:108
-msgid "keyboard|Danish"
-msgstr ""
-
-#: ../keyboard_models.py:111
-msgid "keyboard|Danish (latin1)"
-msgstr ""
-
-#: ../keyboard_models.py:114
-msgid "keyboard|Spanish"
-msgstr ""
-
-#: ../keyboard_models.py:117
-msgid "keyboard|Estonian"
-msgstr ""
-
-#: ../keyboard_models.py:120
-msgid "keyboard|Finnish"
-msgstr ""
-
-#: ../keyboard_models.py:123
-msgid "keyboard|Finnish (latin1)"
-msgstr ""
-
-#: ../keyboard_models.py:126
-msgid "keyboard|French"
-msgstr ""
-
-#: ../keyboard_models.py:129
-msgid "keyboard|French (latin9)"
-msgstr ""
-
-#: ../keyboard_models.py:132
-msgid "keyboard|French (latin1)"
-msgstr ""
-
-#: ../keyboard_models.py:135
-msgid "keyboard|French (pc)"
-msgstr ""
-
-#: ../keyboard_models.py:138
-msgid "keyboard|Swiss French"
-msgstr ""
-
-#: ../keyboard_models.py:141
-msgid "keyboard|Swiss French (latin1)"
-msgstr ""
-
-#: ../keyboard_models.py:144
-msgid "keyboard|Greek"
-msgstr ""
-
-#: ../keyboard_models.py:147
-msgid "keyboard|Gujarati (Inscript)"
-msgstr ""
-
-#: ../keyboard_models.py:150
-msgid "keyboard|Punjabi (Inscript)"
-msgstr ""
-
-#: ../keyboard_models.py:153
-msgid "keyboard|Hungarian"
-msgstr ""
-
-#: ../keyboard_models.py:156
-msgid "keyboard|Hungarian (101 key)"
-msgstr ""
-
-#: ../keyboard_models.py:159
-msgid "keyboard|Icelandic"
-msgstr ""
-
-#: ../keyboard_models.py:162
-msgid "keyboard|Italian"
-msgstr ""
-
-#: ../keyboard_models.py:165
-msgid "keyboard|Italian (IBM)"
-msgstr ""
-
-#: ../keyboard_models.py:168
-msgid "keyboard|Italian (it2)"
-msgstr ""
-
-#: ../keyboard_models.py:171
-msgid "keyboard|Japanese"
-msgstr ""
-
-#: ../keyboard_models.py:174
-msgid "keyboard|Korean"
-msgstr ""
-
-#: ../keyboard_models.py:177
-msgid "keyboard|Latin American"
-msgstr ""
-
-#: ../keyboard_models.py:180
-msgid "keyboard|Macedonian"
-msgstr ""
-
-#: ../keyboard_models.py:183
-msgid "keyboard|Dutch"
-msgstr ""
-
-#: ../keyboard_models.py:186
-msgid "keyboard|Norwegian"
-msgstr ""
-
-#: ../keyboard_models.py:189
-msgid "keyboard|Polish"
-msgstr ""
-
-#: ../keyboard_models.py:192
-msgid "keyboard|Portuguese"
-msgstr ""
-
-#: ../keyboard_models.py:195
-msgid "keyboard|Romanian"
-msgstr ""
-
-#: ../keyboard_models.py:198
-msgid "keyboard|Russian"
-msgstr ""
-
-#: ../keyboard_models.py:201
-msgid "keyboard|Serbian"
-msgstr ""
-
-#: ../keyboard_models.py:204
-msgid "keyboard|Serbian (latin)"
-msgstr ""
-
-#: ../keyboard_models.py:207
-msgid "keyboard|Swedish"
-msgstr ""
-
-#: ../keyboard_models.py:210
-msgid "keyboard|Swiss German"
-msgstr ""
-
-#: ../keyboard_models.py:213
-msgid "keyboard|Swiss German (latin1)"
-msgstr ""
-
-#: ../keyboard_models.py:216
-msgid "keyboard|Slovak (qwerty)"
-msgstr ""
-
-#: ../keyboard_models.py:219
-msgid "keyboard|Slovenian"
-msgstr ""
-
-#: ../keyboard_models.py:222
-msgid "keyboard|Tamil (Inscript)"
-msgstr ""
-
-#: ../keyboard_models.py:225
-msgid "keyboard|Tamil (Typewriter)"
-msgstr ""
-
-#: ../keyboard_models.py:228
-msgid "keyboard|Turkish"
-msgstr ""
-
-#: ../keyboard_models.py:231
-msgid "keyboard|United Kingdom"
-msgstr ""
-
-#: ../keyboard_models.py:234
-msgid "keyboard|Ukrainian"
-msgstr ""
-
-#: ../keyboard_models.py:237
-msgid "keyboard|U.S. International"
-msgstr ""
-
-#: ../keyboard_models.py:240
-msgid "keyboard|U.S. English"
-msgstr ""
-
-#: ../network.py:31
-msgid "IP address is missing."
-msgstr "IP-Adresse fehlt."
-
-#: ../network.py:35
-msgid ""
-"IPv4 addresses must contain four numbers between 0 and 255, separated by "
-"periods."
-msgstr ""
-"IPv4-Adressen müssen vier Oktets mit Zahlen zwischen 0 und 255 enthalten. "
-"Getrennt von Punkten."
-
-#: ../network.py:38
-#, python-format
-msgid "'%s' is not a valid IPv6 address."
-msgstr "'%s' ist keine gültige IPv6-Adresse."
-
-#: ../network.py:40
-#, python-format
-msgid "'%s' is an invalid IP address."
-msgstr "'%s' ist eine ungültige IP-Adresse."
-
-#: ../network.py:52
-msgid "Hostname must be 255 or fewer characters in length."
-msgstr "Hostname muss 255 oder weniger Zeichen enthalten."
-
-#: ../network.py:58
-msgid ""
-"Hostname must start with a valid character in the ranges 'a-z', 'A-Z', or '0-"
-"9'"
-msgstr ""
-"Der Hostname muss mit mit einem gültigen Zeichen beginnen. Das sind 'a-z', "
-"'A-Z' oder '0-9'."
-
-#: ../network.py:63
-msgid ""
-"Hostnames can only contain the characters 'a-z', 'A-Z', '0-9', '-', or '.'"
-msgstr ""
-
-#: ../packages.py:113
-msgid "Warning! This is pre-release software!"
-msgstr "Warnung! Dies ist noch nicht veröffentlichte Software!"
-
-#: ../packages.py:114
-#, python-format
-msgid ""
-"Thank you for downloading this pre-release of %s.\n"
-"\n"
-"This is not a final release and is not intended for use on production "
-"systems. The purpose of this release is to collect feedback from testers, "
-"and it is not suitable for day to day usage.\n"
-"\n"
-"To report feedback, please visit:\n"
-"\n"
-" %s\n"
-"\n"
-"and file a report against '%s'.\n"
-msgstr ""
-"Danke, für das probieren dieser noch nicht veröffentlichten Version von %s.\n"
-"\n"
-"Diese Software ist noch kein finales Release und nicht für den produktiven "
-"Einsatz gedacht. Der Zweck liegt darin Fehler zu finden und Feedback von "
-"Testern zu bekommen.\n"
-"\n"
-"Um Feedback zu geben besuchen Sie\n"
-"\n"
-" %s\n"
-"\n"
-"und senden einen Report über '%s'.\n"
-
-#: ../packages.py:127
-msgid "_Exit"
-msgstr "Ende"
-
-#: ../packages.py:127
-msgid "_Install anyway"
-msgstr "_Trotzdem installieren"
-
-#: ../packages.py:130
-msgid "Your system will now be rebooted..."
-msgstr "Ihr System wird jetzt neu gestartet..."
-
-#: ../packages.py:131 ../tui_confirm.py:37
-msgid "_Back"
-msgstr "Zurück"
-
-#: ../packages.py:132
-msgid "Rebooting System"
-msgstr "Starte das System neu"
-
-#: ../pakfireinstall.py:47
-#, python-format
-msgid "%s MB"
-msgstr "%s MB"
-
-#: ../pakfireinstall.py:50
-#, python-format
-msgid "%s KB"
-msgstr "%s KB"
-
-#: ../pakfireinstall.py:53
-#, python-format
-msgid "%s Byte"
-msgstr "%s Byte"
-
-#: ../pakfireinstall.py:55
-#, python-format
-msgid "%s Bytes"
-msgstr "%s Bytes"
-
-#: ../pakfireinstall.py:134
-msgid "Base system"
-msgstr "Grundsystem"
-
-#: ../pakfireinstall.py:134
-msgid "Installing base system..."
-msgstr "Installiere Basissystem..."
-
-#: ../pakfireinstall.py:171
-msgid "Install Starting"
-msgstr "Starte Installation"
-
-#: ../pakfireinstall.py:172
-msgid "Starting install process. This may take several minutes..."
-msgstr ""
-"Der Installationsprozess wird gestartet. Haben Sie einen Augenblick Geduld..."
-
-#: ../pakfireinstall.py:183
-msgid "Post Install"
-msgstr ""
-
-#: ../pakfireinstall.py:184
-msgid "Performing post install configuration..."
-msgstr ""
-
-#: ../pakfireinstall.py:215
-msgid "Symmetric multiprocessing"
-msgstr ""
-
-#: ../pakfireinstall.py:216
-msgid "Xen guest"
-msgstr "Xen-Gast"
-
-#: ../pakfireinstall.py:226
-msgid "Normal Boot"
-msgstr "Normaler Boot"
-
-#: ../pakfireinstall.py:233
-msgid "Installation Progress"
-msgstr "Installationsprozess"
-
-#: ../partedUtils.py:191 ../tui_partition.py:408
-msgid "Foreign"
-msgstr ""
-
-#: ../partedUtils.py:231
-#, python-format
-msgid ""
-"/dev/%s currently has a %s partition layout. To use this drive for the "
-"installation of %s, it must be re-initialized, causing the loss of ALL DATA "
-"on this drive.\n"
-"\n"
-"Would you like to re-initialize this drive?"
-msgstr ""
-"/dev/%s hat momentan ein %s Partitionslayout. Um dieses Laufwerk für eine %s-"
-"Installation zu nutzen muss es reinitialisiert werden, was ALLE DATEN auf "
-"diesem Laufwerk vernichten wird.\n"
-"\n"
-"Möchten Sie das Laufwerk reinitialisieren?"
-
-#: ../partedUtils.py:239
-msgid "_Ignore drive"
-msgstr "_Ignoriere Laufwerk"
-
-#: ../partedUtils.py:240
-msgid "_Re-initialize drive"
-msgstr "_Reinitialisiere Laufwerk"
-
-#: ../partedUtils.py:532
-#, python-format
-msgid ""
-"The partition table on device %s was unreadable. To create new partitions it "
-"must be initialized, causing the loss of ALL DATA on this drive.\n"
-"\n"
-"This operation will override any previous installation choices about which "
-"drives to ignore.\n"
-"\n"
-"Would you like to initialize this drive, erasing ALL DATA?"
-msgstr ""
-"Die Partitionstabelle auf %s war nicht lesbar. Um neue Partitionen zu "
-"erstellen muss diese initialisiert werden, was ALLE DATEN auf diesem "
-"Laufwerk vernichten wird.\n"
-"\n"
-"Diese Operation wird alle vorhergegangen Entscheidungen über auszulassende "
-"Laufwerke verwerfen.\n"
-"\n"
-"Möchten Sie dieses Laufwerk initialisieren, was ALLE DATEN vernichten wird?"
-
-#: ../partedUtils.py:569
-#, python-format
-msgid ""
-"The drive /dev/%s has more than 15 partitions on it. The SCSI subsystem in "
-"the Linux kernel does not allow for more than 15 partitons at this time. "
-"You will not be able to make changes to the partitioning of this disk or use "
-"any partitions beyond /dev/%s15 in %s"
-msgstr ""
-"Das Laufwerk /dev/%s hat mehr als 15 Partitionen. Das SCSI-Subsystem des "
-"Linux-Kernel erlaubt im Augenblick nicht mehr als 15 Partitionen. Sie werden "
-"keine Partitionsänderungen vornehmen und auf keine Partitionen nach /dev/%"
-"s15 auf %s zugreifen können."
-
-#: ../partedUtils.py:659
-msgid "No Drives Found"
-msgstr "Keine Laufwerke gefunden"
-
-#: ../partedUtils.py:660
-msgid ""
-"An error has occurred - no valid devices were found on which to create new "
-"file systems. Please check your hardware for the cause of this problem."
-msgstr ""
-"Ein Fehler trat auf. - Es wurden keine Laufwerke gefunden, auf welche das "
-"Dateisystem erstellt werden könnte. Bitte überprüfen Sie ihre Hardware für "
-"die Ursache des Problems."
-
-#: ../partIntfHelpers.py:50
-#, python-format
-msgid ""
-"The mount point %s is invalid. Mount points must start with '/' and cannot "
-"end with '/', and must contain printable characters and no spaces."
-msgstr ""
-"Der Einhängepunkt %s ist ungültig. Einhängepunkte müssen mit einem '/' "
-"beginnen und dürfen nicht mit einem '/' enden. Ebenso dürfen sie nur "
-"druckbare Zeichen enthalten, jedoch keine Leerzeichen."
-
-#: ../partIntfHelpers.py:57
-msgid "Please specify a mount point for this partition."
-msgstr "Geben Sie einen Einhängepunkt für diese Partition an."
-
-#: ../partIntfHelpers.py:74 ../partIntfHelpers.py:80 ../partIntfHelpers.py:90
-#: ../partIntfHelpers.py:111
-msgid "Unable To Delete"
-msgstr ""
-
-#: ../partIntfHelpers.py:75
-msgid "You must first select a partition to delete."
-msgstr "Sie müssen zuerste eine Partition auswählen um diese zu entfernen."
-
-#: ../partIntfHelpers.py:81
-msgid "You cannot delete free space."
-msgstr "Sie können keinen freien Platz löschen."
-
-#: ../partIntfHelpers.py:91
-#, python-format
-msgid ""
-"You cannot delete this partition, as it is an extended partition which "
-"contains %s"
-msgstr ""
-"Sie können diese Partition nicht löschen, da sie eine erweiterte Partition "
-"ist, welche %s enthält."
-
-#: ../partIntfHelpers.py:106
-msgid "This partition is holding the data for the hard drive install."
-msgstr "Diese Partition beinhaltet die Daten für die Festplatten-Installation."
-
-#: ../partIntfHelpers.py:112
-msgid ""
-"You cannot delete this partition:\n"
-"\n"
-msgstr ""
-"Sie können diese Partition nicht löschen:\n"
-"\n"
-
-#: ../partIntfHelpers.py:146 ../partIntfHelpers.py:391
-msgid "Confirm Delete"
-msgstr "Löschen bestätigen"
-
-#: ../partIntfHelpers.py:147
-#, python-format
-msgid "You are about to delete all partitions on the device '/dev/%s'."
-msgstr ""
-"Sie sind im Begriff alle Partitionen auf dem Laufwerk '/dev/%s' zu löschen."
-
-#: ../partIntfHelpers.py:150 ../partIntfHelpers.py:392
-msgid "_Delete"
-msgstr "_Löschen"
-
-#: ../partIntfHelpers.py:206
-msgid "Notice"
-msgstr "Hinweis"
-
-#: ../partIntfHelpers.py:207
-#, python-format
-msgid ""
-"The following partitions were not deleted because they are in use:\n"
-"\n"
-"%s"
-msgstr ""
-"Die folgenden Partitionen wurden nicht entfert, weil sie in Verwendung "
-"sind:\n"
-"\n"
-"%s"
-
-#: ../partIntfHelpers.py:222 ../partIntfHelpers.py:238
-#: ../partIntfHelpers.py:249
-msgid "Unable To Edit"
-msgstr ""
-
-#: ../partIntfHelpers.py:223
-msgid "You must select a partition to edit"
-msgstr "Sie müssen eine Partition auswählen um diese zu editieren"
-
-#: ../partIntfHelpers.py:239
-#, python-format
-msgid ""
-"You cannot edit this partition, as it is an extended partition which "
-"contains %s"
-msgstr ""
-
-#: ../partIntfHelpers.py:250
-msgid ""
-"You cannot edit this partition:\n"
-"\n"
-msgstr ""
-
-#: ../partIntfHelpers.py:272
-msgid "Format as Swap?"
-msgstr "Als Swap formatieren?"
-
-#: ../partIntfHelpers.py:273
-#, python-format
-msgid ""
-"/dev/%s has a partition type of 0x82 (Linux swap) but does not appear to be "
-"formatted as a Linux swap partition.\n"
-"\n"
-"Would you like to format this partition as a swap partition?"
-msgstr ""
-
-#: ../partIntfHelpers.py:288
-#, python-format
-msgid "You need to select at least one hard drive to install %s."
-msgstr ""
-
-#: ../partIntfHelpers.py:293
-msgid ""
-"You have chosen to use a pre-existing partition for this installation "
-"without formatting it. We recommend that you format this partition to make "
-"sure files from a previous operating system installation do not cause "
-"problems with this installation of Linux. However, if this partition "
-"contains files that you need to keep, such as home directories, then "
-"continue without formatting this partition."
-msgstr ""
-
-#: ../partIntfHelpers.py:301
-msgid "Format?"
-msgstr "Formatieren?"
-
-#: ../partIntfHelpers.py:302
-msgid "_Modify Partition"
-msgstr "_Bearbeite Partition"
-
-#: ../partIntfHelpers.py:302
-msgid "Do _Not Format"
-msgstr "_Nicht formatieren"
-
-#: ../partIntfHelpers.py:311
-msgid "Error with Partitioning"
-msgstr ""
-
-#: ../partIntfHelpers.py:312
-#, python-format
-msgid ""
-"The following critical errors exist with your requested partitioning scheme. "
-"These errors must be corrected prior to continuing with your install of %s.\n"
-"\n"
-"%s"
-msgstr ""
-
-#: ../partIntfHelpers.py:326
-msgid "Partitioning Warning"
-msgstr "Partitionierungswarnung"
-
-#: ../partIntfHelpers.py:327
-#, python-format
-msgid ""
-"The following warnings exist with your requested partition scheme.\n"
-"\n"
-"%s\n"
-"\n"
-"Would you like to continue with your requested partitioning scheme?"
-msgstr ""
-
-#: ../partIntfHelpers.py:340
-msgid ""
-"The following pre-existing partitions have been selected to be formatted, "
-"destroying all data."
-msgstr ""
-
-#: ../partIntfHelpers.py:342
-msgid ""
-"Select 'Yes' to continue and format these partitions, or 'No' to go back and "
-"change these settings."
-msgstr ""
-
-#: ../partIntfHelpers.py:348
-msgid "Format Warning"
-msgstr "Formatierungswarnung"
-
-#: ../partIntfHelpers.py:387
-#, python-format
-msgid "You are about to delete the /dev/%s partition."
-msgstr "Sie sind dabei die Partition /dev/%s zu löschen."
-
-#: ../partIntfHelpers.py:389
-msgid "The partition you selected will be deleted."
-msgstr "Die ausgewählte Partition wird gelöscht."
-
-#: ../partIntfHelpers.py:398
-msgid "Confirm Reset"
-msgstr ""
-
-#: ../partIntfHelpers.py:399
-msgid ""
-"Are you sure you want to reset the partition table to its original state?"
-msgstr ""
-
-#: ../partitioning.py:36
-msgid "Installation cannot continue."
-msgstr ""
-
-#: ../partitioning.py:37
-msgid ""
-"The partitioning options you have chosen have already been activated. You "
-"can no longer return to the disk editing screen. Would you like to continue "
-"with the installation process?"
-msgstr ""
-
-#: ../partitioning.py:65
-msgid "Low Memory"
-msgstr "Wenig Arbeitsspeicher"
-
-#: ../partitioning.py:66
-msgid ""
-"As you don't have much memory in this machine, we need to turn on swap space "
-"immediately. To do this we'll have to write your new partition table to the "
-"disk immediately. Is that OK?"
-msgstr ""
-"Da sich in dem System nicht ausreichend Arbeitsspeicher befindet ist es "
-"nötig den Swap sofort zu aktivieren. Dazu muss die neue Partitionstabelle "
-"jetzt geschrieben werden. Ist das OK?"
-
-#: ../partitions.py:311
-#, python-format
-msgid ""
-"You have not defined a root partition (/), which is required for "
-"installation of %s to continue."
-msgstr ""
-"Sie haben keine Root-Partition (/) angegeben, welche jedoch für die "
-"Installation von %s notwendig ist."
-
-#: ../partitions.py:316
-#, python-format
-msgid ""
-"Your root partition is less than 250 megabytes which is usually too small to "
-"install %s."
-msgstr ""
-
-#: ../partitions.py:333
-msgid ""
-"Your boot partition isn't on one of the first four partitions and thus won't "
-"be bootable."
-msgstr ""
-"Ihre Boot-Partition ist nicht eine der ersten vier Partitionen auf dem "
-"Datenträger und wird daher nicht bootbar sein."
-
-#: ../partitions.py:342
-#, python-format
-msgid ""
-"Your %s partition is less than %s megabytes which is lower than recommended "
-"for a normal %s install."
-msgstr ""
-"Ihre %s-Partition ist kleiner als %s Megabytes, was für eine normale "
-"Installation von %s nicht empfohlen ist."
-
-#: ../partitions.py:374
-msgid ""
-"Installing on a USB device. This may or may not produce a working system."
-msgstr ""
-"Sie installieren auf einem USB-Laufwerk, was kein funktionierendes System "
-"produzieren könnte."
-
-#: ../partitions.py:378
-msgid ""
-"Installing on a FireWire device. This may or may not produce a working "
-"system."
-msgstr ""
-"Sie installieren auf einem Firewire-Laufwerk, was kein funktionierendes "
-"System produzieren könnte."
-
-#: ../partitions.py:391
-msgid ""
-"You have not specified a swap partition. Although not strictly required in "
-"all cases, it will significantly improve performance for most installations."
-msgstr "Sie haben keine Swap-Partition angelegt."
-
-#: ../partitions.py:398
-#, python-format
-msgid ""
-"You have specified more than 32 swap devices. The kernel for %s only "
-"supports 32 swap devices."
-msgstr ""
-
-#: ../partitions.py:409
-#, python-format
-msgid ""
-"You have allocated less swap space (%dM) than available RAM (%dM) on your "
-"system. This could negatively impact performance."
-msgstr ""
-
-#: ../partitions.py:485
-msgid "the partition in use by the installer."
-msgstr ""
-
-#: ../partRequests.py:182
-#, python-format
-msgid ""
-"This mount point is invalid. The %s directory must be on the / file system."
-msgstr ""
-
-#: ../partRequests.py:185
-#, python-format
-msgid ""
-"The mount point %s cannot be used. It must be a symbolic link for proper "
-"system operation. Please select a different mount point."
-msgstr ""
-
-#: ../partRequests.py:192
-msgid "This mount point must be on a linux file system."
-msgstr ""
-
-#: ../partRequests.py:212
-#, python-format
-msgid ""
-"The mount point \"%s\" is already in use, please choose a different mount "
-"point."
-msgstr ""
-
-#: ../partRequests.py:226
-#, python-format
-msgid ""
-"The size of the %s partition (%10.2f MB) exceeds the maximum size of %10.2f "
-"MB."
-msgstr ""
-
-#: ../partRequests.py:414
-#, python-format
-msgid ""
-"The size of the requested partition (size = %s MB) exceeds the maximum size "
-"of %s MB."
-msgstr ""
-
-#: ../partRequests.py:419
-#, python-format
-msgid "The size of the requested partition is negative! (size = %s MB)"
-msgstr ""
-
-#: ../partRequests.py:423
-msgid "Partitions can't start below the first cylinder."
-msgstr ""
-
-#: ../partRequests.py:426
-msgid "Partitions can't end on a negative cylinder."
-msgstr ""
-
-#: ../tui_bootloader.py:27
-msgid "Which boot loader would you like to use?"
-msgstr ""
-
-#: ../tui_bootloader.py:37
-msgid "Use GRUB Boot Loader"
-msgstr ""
-
-#: ../tui_bootloader.py:38
-msgid "No Boot Loader"
-msgstr ""
-
-#: ../tui_bootloader.py:41 ../tui_bootloader.py:103 ../tui_bootloader.py:161
-#: ../tui_bootloader.py:278 ../tui_bootloader.py:383
-msgid "Boot Loader Configuration"
-msgstr ""
-
-#: ../tui_bootloader.py:58
-msgid "Skip Boot Loader"
-msgstr ""
-
-#: ../tui_bootloader.py:59
-msgid ""
-"You have elected not to install any boot loader, which is not recommended "
-"unless you have an advanced need. Booting your system into Linux directly "
-"from the hard drive almost always requires a boot loader.\n"
-"\n"
-"Are you sure you want to skip boot loader installation?"
-msgstr ""
-
-#: ../tui_bootloader.py:88
-msgid ""
-"A few systems need to pass special options to the kernel at boot time to "
-"function properly. If you need to pass boot options to the kernel, enter "
-"them now. If you don't need any or aren't sure, leave this blank."
-msgstr ""
-
-#: ../tui_bootloader.py:97
-msgid "Force use of LBA32 (not normally required)"
-msgstr ""
-
-#: ../tui_bootloader.py:120
-msgid ""
-"If LBA32 is not supported by your system's BIOS, forcing its use can prevent "
-"your machine from booting.\n"
-"\n"
-"Would you like to continue and force LBA32 mode?"
-msgstr ""
-
-#: ../tui_bootloader.py:162
-msgid "Where do you want to install the boot loader?"
-msgstr "Wo möchten Sie den Bootloader installieren?"
-
-#: ../tui_bootloader.py:188 ../tui_bootloader.py:255 ../tui_partition.py:844
-msgid "Device"
-msgstr "Partition"
-
-#: ../tui_bootloader.py:189 ../tui_bootloader.py:255
-msgid "Boot label"
-msgstr ""
-
-#: ../tui_bootloader.py:193
-msgid "Clear"
-msgstr ""
-
-#: ../tui_bootloader.py:201
-msgid "Edit Boot Label"
-msgstr ""
-
-#: ../tui_bootloader.py:219 ../tui_bootloader.py:224
-msgid "Invalid Boot Label"
-msgstr "Ungültiges Label"
-
-#: ../tui_bootloader.py:220
-msgid "Boot label may not be empty."
-msgstr ""
-
-#: ../tui_bootloader.py:225
-msgid "Boot label contains illegal characters."
-msgstr ""
-
-#: ../tui_bootloader.py:255
-msgid "Default"
-msgstr "Standard"
-
-#: ../tui_bootloader.py:273
-#, python-format
-msgid ""
-"The boot manager %s uses can boot other operating systems as well. Please "
-"tell me what partitions you would like to be able to boot and what label you "
-"want to use for each of them."
-msgstr ""
-
-#: ../tui_bootloader.py:286
-msgid ""
-" <Space> select | <F2> select default | <F4> delete | <F12> next screen>"
-msgstr "<Leertaste>,<+>,<-> Auswahl | <F2> Laufwerk hinzufügen | <F12> Weiter"
-
-#: ../tui_bootloader.py:335
-msgid "Cannot Delete"
-msgstr "Kann nicht löschen"
-
-#: ../tui_bootloader.py:336
-#, python-format
-msgid ""
-"This boot target cannot be deleted because it is for the %s system you are "
-"about to install."
-msgstr ""
-
-#: ../tui_bootloader.py:378
-msgid ""
-"A boot loader password prevents users from passing arbitrary options to the "
-"kernel. For highest security, you should set a password, but a password is "
-"not necessary for more casual users."
-msgstr ""
-
-#: ../tui_bootloader.py:386
-msgid "Use a GRUB Password"
-msgstr "Benutze ein GRUB-Passwort"
-
-#: ../tui_bootloader.py:399
-msgid "Boot Loader Password:"
-msgstr "Bootloader-Passwort:"
-
-#: ../tui_bootloader.py:400
-msgid "Confirm:"
-msgstr "Bestätigen:"
-
-#: ../tui_bootloader.py:429
-msgid "Passwords Do Not Match"
-msgstr "Passwörter stimmen nicht überein"
-
-#: ../tui_bootloader.py:430
-msgid "Passwords do not match"
-msgstr "Die Passwörter stimmen nicht überein"
-
-#: ../tui_bootloader.py:434
-msgid "Password Too Short"
-msgstr "Das Passwort ist zu kurz"
-
-#: ../tui_bootloader.py:435
-msgid "Boot loader password is too short"
-msgstr "Das Bootloader-Passwort ist zu kurz"
-
-#: ../tui_bootloader.py:440
-msgid ""
-"Your boot loader password is shorter than six characters. We recommend a "
-"longer boot loader password.\n"
-"\n"
-"Would you like to continue with this password?"
-msgstr ""
-"Ihr Bootloader-Passwort ist kürzer als 6 Zeichen. Wir empfehlen einen "
-"längeren Schlüssel zu nehmen.\n"
-"\n"
-"Möchten Sie trotzdem mit dem eingegebenen Passwort fortfahren?"
-
-#: ../tui_complete.py:25
-msgid ""
-"Press <Enter> to end the installation process.\n"
-"\n"
-msgstr ""
-"Drücken Sie <Enter> um den Installationprozess zu beenden.\n"
-"\n"
-
-#: ../tui_complete.py:26
-msgid "<Enter> to exit"
-msgstr "<Enter> zum Beenden"
-
-#: ../tui_complete.py:30
-#, python-format
-msgid ""
-"Congratulations, your %s installation is complete.\n"
-"\n"
-"%s%s"
-msgstr ""
-"Herzlichen Glückwunsch, die Installation von %s wurde erfolgreich beendet.\n"
-"\n"
-"%s%s"
-
-#: ../tui_complete.py:33
-#, python-format
-msgid ""
-"For information on errata (updates and bug fixes), visit %s.\n"
-"\n"
-"Information on using your system is available in the %s wiki at %s."
-msgstr ""
-"Für weitere Informationen über Bugfixes besuchen Sie %s.\n"
-"\n"
-"Informationen über das System erhalten Sie im %s-Wiki auf %s."
-
-#: ../tui_complete.py:39
-msgid "Complete"
-msgstr "Fertig"
-
-#: ../tui_confirm.py:23
-msgid "Installation to begin"
-msgstr ""
-
-#: ../tui_confirm.py:24
-msgid ""
-"Now, we got all information we need for installation. If there is something "
-"you want change you can still go back. If not choose OK to start."
-msgstr ""
-
-#: ../tui_confirm.py:34
-msgid "Reboot?"
-msgstr "Neustarten?"
-
-#: ../tui_confirm.py:35
-msgid "The system will be rebooted now."
-msgstr "Ihr System wird jetzt neu gestartet."
-
-#: ../tui_keyboard.py:36
-msgid "Keyboard Selection"
-msgstr "Tastaturauswahl"
-
-#: ../tui_keyboard.py:37
-msgid "Which model keyboard is attached to this computer?"
-msgstr "Welches Tastaturmodell ist an den Computer angeschlossen?"
-
-#: ../tui_language.py:39
-msgid "Language Selection"
-msgstr "Sprachauswahl"
-
-#: ../tui_language.py:40
-msgid "What language would you like to use during the installation process?"
-msgstr "Welche Sprache möchten Sie für den Installationsprozess nutzen?"
-
-#: ../tui_network.py:39
-msgid "Hostname"
-msgstr "Hostname"
-
-#: ../tui_network.py:42
-msgid ""
-"Please name this computer. The hostname identifies the computer on a "
-"network."
-msgstr ""
-
-#: ../tui_network.py:63 ../tui_network.py:70
-msgid "Invalid Hostname"
-msgstr "Ungültiger Hostname"
-
-#: ../tui_network.py:64
-msgid "You have not specified a hostname."
-msgstr "Sie haben keinen Hostnamen eingegeben."
-
-#: ../tui_network.py:71
-#, python-format
-msgid ""
-"The hostname \"%s\" is not valid for the following reason:\n"
-"\n"
-"%s"
-msgstr ""
-
-#: ../tui_partition.py:41
-msgid "Must specify a value"
-msgstr "Bitte geben Sie einen Wert ein"
-
-#: ../tui_partition.py:44
-msgid "Requested value is not an integer"
-msgstr "Der eingegebene Wert ist kein Integer"
-
-#: ../tui_partition.py:46
-msgid "Requested value is too large"
-msgstr "Der eingegebene Wert ist zu groß"
-
-#: ../tui_partition.py:95 ../tui_partition.py:132
-msgid "Free space"
-msgstr "Freier Platz"
-
-#: ../tui_partition.py:97
-msgid "Extended"
-msgstr "Erweitert"
-
-#: ../tui_partition.py:111
-msgid "None"
-msgstr "Keins"
-
-#: ../tui_partition.py:178
-#, python-format
-msgid "Could not allocate requested partitions: %s."
-msgstr "Konnte die Partition nicht finden: %s."
-
-#: ../tui_partition.py:182
-#, python-format
-msgid "Warning: %s"
-msgstr "Warnung: %s"
-
-#: ../tui_partition.py:183
-msgid "Modify Partition"
-msgstr "Partition bearbeiten"
-
-#: ../tui_partition.py:183
-msgid "Add anyway"
-msgstr "Trotzdem hinzufügen"
-
-#: ../tui_partition.py:201 ../tui_partition.py:203 ../tui_partition.py:205
-#: ../tui_partition.py:230
-msgid "<Not Applicable>"
-msgstr "<Nicht verfügbar>"
-
-#: ../tui_partition.py:220
-msgid "Mount Point:"
-msgstr "Einhängepunkt:"
-
-#: ../tui_partition.py:239
-msgid "File System type:"
-msgstr "Dateisystem-Typ:"
-
-#: ../tui_partition.py:270
-msgid "Allowable Drives:"
-msgstr ""
-
-#: ../tui_partition.py:292 ../tui_partition.py:371 ../tui_partition.py:419
-msgid "Size (MB):"
-msgstr "Größe (MB):"
-
-#: ../tui_partition.py:324
-msgid "Fixed Size:"
-msgstr "Feste Größe:"
-
-#: ../tui_partition.py:326
-msgid "Fill maximum size of (MB):"
-msgstr "Maximale Größe in MB:"
-
-#: ../tui_partition.py:330
-msgid "Fill all available space:"
-msgstr "Verfügbaren Speicherplatz ausfüllen:"
-
-#: ../tui_partition.py:351
-msgid "Start Cylinder:"
-msgstr "Startzylinder:"
-
-#: ../tui_partition.py:364
-msgid "End Cylinder:"
-msgstr "Endzylinder:"
-
-#: ../tui_partition.py:386
-msgid "Number of spares?"
-msgstr ""
-
-#: ../tui_partition.py:400
-msgid "File System Type:"
-msgstr "Dateisystem:"
-
-#: ../tui_partition.py:413
-msgid "File System Label:"
-msgstr "Dateisystemlabel:"
-
-#: ../tui_partition.py:424
-msgid "File System Option:"
-msgstr "Dateisystemoption:"
-
-#: ../tui_partition.py:427 ../tui_partition.py:652
-#, python-format
-msgid "Format as %s"
-msgstr "Formatieren als %s"
-
-#: ../tui_partition.py:429 ../tui_partition.py:654
-#, python-format
-msgid "Migrate to %s"
-msgstr "Migrieren zu %s"
-
-#: ../tui_partition.py:431 ../tui_partition.py:656
-msgid "Leave unchanged"
-msgstr "Beibehalten"
-
-#: ../tui_partition.py:446 ../tui_partition.py:629
-msgid "File System Options"
-msgstr "Dateisystemoptionen"
-
-#: ../tui_partition.py:449
-msgid ""
-"Please choose how you would like to prepare the file system on this "
-"partition."
-msgstr ""
-"Bitte wählen Sie, wie sie das Dateisystem für diese Partition vorbereiten "
-"wollen."
-
-#: ../tui_partition.py:457 ../tui_partition.py:607
-msgid "Check for bad blocks"
-msgstr "Untersuche nach defekten Blöcken"
-
-#: ../tui_partition.py:461
-msgid "Leave unchanged (preserve data)"
-msgstr "Beibehalten (erhält die Daten)"
-
-#: ../tui_partition.py:470
-msgid "Format as:"
-msgstr "Formatieren als:"
-
-#: ../tui_partition.py:489
-msgid "Migrate to:"
-msgstr "Migrieren nach:"
-
-#: ../tui_partition.py:559
-msgid "Add Partition"
-msgstr "Partition hinzufügen"
-
-#: ../tui_partition.py:601
-msgid "Force to be a primary partition"
-msgstr "Erzwinge primäre Partition"
-
-#: ../tui_partition.py:684 ../tui_partition.py:738
-msgid "Invalid Entry for Partition Size"
-msgstr "Ungültige Eingabe für die Partitionsgröße"
-
-#: ../tui_partition.py:696
-msgid "Invalid Entry for Maximum Size"
-msgstr "Ungültige Eingabe für die maximale Größe"
-
-#: ../tui_partition.py:716
-msgid "Invalid Entry for Starting Cylinder"
-msgstr "Ungültige Eingabe für den Startzylinder"
-
-#: ../tui_partition.py:730
-msgid "Invalid Entry for End Cylinder"
-msgstr "Ungültige Eingabe für den Endzylinder"
-
-#: ../tui_partition.py:748 ../tui_partition.py:769
-msgid "Error With Request"
-msgstr "Fehler im Request"
-
-#: ../tui_partition.py:838
-msgid "Partitioning"
-msgstr "Partitionierung"
-
-#: ../tui_partition.py:844
-msgid "Start"
-msgstr "Startsektor"
-
-#: ../tui_partition.py:844
-msgid "End"
-msgstr "Endsektor"
-
-#: ../tui_partition.py:844
-msgid "Size"
-msgstr "Größe"
-
-#: ../tui_partition.py:844
-msgid "Type"
-msgstr "Typ"
-
-#: ../tui_partition.py:844
-msgid "Mount Point"
-msgstr "Mount-Point"
-
-#: ../tui_partition.py:848
-msgid "New"
-msgstr "Neu"
-
-#: ../tui_partition.py:850
-msgid "Delete"
-msgstr "Löschen"
-
-#: ../tui_partition.py:853
-msgid ""
-" F1-Help F2-New F3-Edit F4-Delete F5-Reset F12-OK "
-msgstr " F1-Hilfe F2-Neu F3-Bearbeiten F4-Löschen F5-Zurücksetzen F12-OK"
-
-#: ../tui_partition.py:883
-msgid "No Root Partition"
-msgstr "Keine Root-Partition"
-
-#: ../tui_partition.py:884
-msgid "Installation requires a / partition."
-msgstr "Die Installation erfordert die Konfiguration einer /-Partition."
-
-#: ../tui_partition.py:923
-msgid "Partitioning Type"
-msgstr "Partitionstyp"
-
-#: ../tui_partition.py:925
-msgid ""
-"Installation requires partitioning of your hard drive. The default layout "
-"is reasonable for most users. You can either choose to use this or create "
-"your own."
-msgstr ""
-"Für die Installation ist es nötig die Festplatten passend zu partitionieren. "
-"Das Standardlayout genügt für die meisten Nutzer. Experten können eigene "
-"Anpassungen vornehmen."
-
-#: ../tui_partition.py:932
-msgid "Remove all partitions on selected drives and create default layout"
-msgstr "Alle Partitionen löschen und Standardlayout erstellen"
-
-#: ../tui_partition.py:933
-msgid "Create custom layout"
-msgstr "Benutzerdefiniertes Layout erstellen"
-
-#: ../tui_partition.py:947
-msgid "Which drive(s) do you want to use for this installation?"
-msgstr "Welche(s) Laufwerk(e) möchten Sie für die Installation nutzen?"
-
-#: ../tui_partition.py:960
-msgid "<Space>,<+>,<-> selection | <F2> Add drive | <F12> next screen"
-msgstr "<Leertaste>,<+>,<-> Auswahl | <F2> Laufwerk hinzufügen | <F12> Weiter"
-
-#: ../tui_partition.py:1029
-msgid "Review Partition Layout"
-msgstr "Ansicht des Partitionslayout"
-
-#: ../tui_partition.py:1030
-msgid "Review and modify partitioning layout?"
-msgstr "Möchten Sie das Partitionslayout ansehen oder bearbeiten?"
-
-#: ../tui_progress.py:52
-msgid "File Installation"
-msgstr "Dateiinstallation"
-
-#: ../tui.py:118
-msgid "Exception Occurred"
-msgstr "Fehler aufgetreten"
-
-#: ../tui.py:189
-msgid "Error!"
-msgstr "Fehler!"
-
-#: ../tui.py:190
-#, python-format
-msgid ""
-"An error occurred when attempting to load an pomona interface component.\n"
-"\n"
-"className = %s\n"
-"\n"
-"Error: %s"
-msgstr ""
-
-#: ../tui.py:195 ../tui.py:197
-msgid "Exit"
-msgstr "Ende"
-
-#: ../tui.py:195 ../tui.py:391
-msgid "Retry"
-msgstr "Wiederholen"
-
-#: ../tui.py:220
-msgid "Cancelled"
-msgstr "Abgebrochen"
-
-#: ../tui.py:221
-msgid "I can't go to the previous step from here. You will have to try again."
-msgstr ""
-"Es konnte nicht zum vorhergeneden Installationsschritt gewechselt werden. "
-"Bitte wiederholen Sie den Schritt."
-
-#: ../tui.py:235
-#, python-format
-msgid "Welcome to %s"
-msgstr "Willkommen bei %s"
-
-#: ../tui.py:238
-msgid ""
-" <F1> for help | <Tab> between elements | <Space> selects | <F12> next screen"
-msgstr ""
-
-#: ../tui.py:240
-msgid ""
-" <Tab>/<Alt-Tab> between elements | <Space> selects | <F12> next "
-"screen"
-msgstr ""
-
-#: ../tui.py:285
-msgid "Help not available"
-msgstr "Keine Hilfe verfügbar"
-
-#: ../tui.py:286
-msgid "No help is available for this step of the install."
-msgstr "Es ist keine Hilfe zu diesem Installationsschritt verfügbar."
-
-#: ../tui.py:387
-msgid "Fix"
-msgstr "Korrigieren"
-
-#: ../tui.py:392
-msgid "Ignore"
-msgstr "Ignorieren"
-
-#: ../tui_timezone.py:63
-msgid "In which time zone are you located?"
-msgstr "In welcher Zeitzone befinden Sie sich?"
-
-#: ../tui_timezone.py:78
-msgid "System clock uses UTC"
-msgstr "Die Systemuhr ist auf UTC eingestellt."
-
-#: ../tui_timezone.py:81
-msgid "Time Zone Selection"
-msgstr "Zeitzonenauswahl"
-
-#: ../tui_userauth.py:29
-msgid "Root Password"
-msgstr "Root-Passwort"
-
-#: ../tui_userauth.py:31
-msgid ""
-"Pick a root password. You must type it twice to ensure you know it and do "
-"not make a typing mistake. Remember that the root password isa critical part "
-"of system security!"
-msgstr ""
-"Wählen Sie ein Root-Passwort. Es muss zweimal eingegeben werden um "
-"Tippfehler zu vermeiden. Bedenken Sie: Das Root-Passwort ist ein kritischer "
-"Teil der Systemsicherheit."
-
-#: ../tui_userauth.py:41
-msgid "Password:"
-msgstr "Passwort:"
-
-#: ../tui_userauth.py:42
-msgid "Password (confirm):"
-msgstr "Passwort (bestätigen):"
-
-#: ../tui_userauth.py:59
-msgid "Password Length"
-msgstr "Passwortlänge"
-
-#: ../tui_userauth.py:60
-msgid "The root password must be at least 6 characters long."
-msgstr "Das Root-Passwort muss mindestens 6 Zeichen lang sein."
-
-#: ../tui_userauth.py:63
-msgid "Password Mismatch"
-msgstr "Passwort-Fehler"
-
-#: ../tui_userauth.py:64
-msgid "The passwords you entered were different. Please try again."
-msgstr "Die eingegebenen Passwörter stimmen nicht überein."
-
-#: ../tui_userauth.py:67
-msgid "Error with Password"
-msgstr "Fehler im Passwort"
-
-#: ../tui_userauth.py:68
-msgid ""
-"Requested password contains non-ASCII characters, which are not allowed."
-msgstr ""
-"Das eingegebene Passwort enthält nicht-ASCII-Zeichen, welche nicht erlaubt "
-"sind."
-
-#: ../tui_welcome.py:12
-#, python-format
-msgid "%s"
-msgstr "%s"
-
-#: ../tui_welcome.py:13
-#, python-format
-msgid ""
-"Welcome to %s!\n"
-"\n"
-msgstr ""
-"Willkommen bei %s!\n"
-"\n"
-
-#. generated from lang-table
-msgid "English"
-msgstr "Englisch"
-
-#. generated from lang-table
-msgid "German"
-msgstr "Deutsch"
-
-#. generated from lang-table
-msgid "Danish"
-msgstr "Dänisch"
-
-#~ msgid "Checking for Bad Blocks"
-#~ msgstr "Untersuche nach defekten Blöcken"
-
-#~ msgid "Probing CDROM"
-#~ msgstr "Suche CDROM"
-
-#~ msgid "Searching for a valid disc on /dev/%s..."
-#~ msgstr "Suche nach einer gültigen CD in /dev/%s..."
-
-#~ msgid "Wrong CDROM"
-#~ msgstr "Falsche CDROM"
-
-#~ msgid "That's not the correct %s CDROM in /dev/%s."
-#~ msgstr ""
-#~ "Bei der eingelegten CDROM in /dev/%s handelt es sich nicht um die "
-#~ "richtige CDROM für %s."
-
-#~ msgid "Insert CDROM"
-#~ msgstr "CDROM einlegen"
-
-#~ msgid "Please insert the %s disc to continue."
-#~ msgstr "Bitte legen Sie die %s CD ein um fortzufahren."
-
-#~ msgid "IPFire"
-#~ msgstr "IPFire"
-
-#~ msgid "Disk Partitioning Setup"
-#~ msgstr "Plattenpartitionierungssetup"
-
-#~ msgid "Autopartition"
-#~ msgstr "Autopartitionierung"
-
-#~ msgid "Disk Druid"
-#~ msgstr "Disk Druid"
-
-#~ msgid "Dump Written"
-#~ msgstr "Dump wurde geschrieben"
-
-#~ msgid "Dump Not Written"
-#~ msgstr "Dump wurde nicht geschrieben"
-
-#~ msgid "Re_try"
-#~ msgstr "Wiederholen"
-
-#~ msgid "Source Type"
-#~ msgstr "Quelltyp"
-
-#~ msgid ""
-#~ "In installation you have to choose a source for the installation files. "
-#~ "Mostly you will choose the disc here, but you are also able to install by "
-#~ "HTTP, FTP hard disk or usb-key."
-#~ msgstr ""
-#~ "Bei der Installation haben Sie die Auswahl zwischen verschiedenen "
-#~ "Quellmedien. Die Meisten werden hier die CD auswählen, jedoch ist auch "
-#~ "eine Installation über HTTP, FTP, Festplatte oder USB-Stick möglich."
-
-#~ msgid "Install Disc"
-#~ msgstr "Installations-CD"
-
-#~ msgid "Internet Source"
-#~ msgstr "Internet-Quelle"
-
-#~ msgid "External Drive"
-#~ msgstr "Externes Laufwerk"
-
-#~ msgid "No CDROM found"
-#~ msgstr "Keine Laufwerke gefunden"
-
-#~ msgid ""
-#~ "You choosed to install from an installtion disc, but there was no cdrom "
-#~ "drive found on the system. Please choose another installation method."
-#~ msgstr ""
-#~ "Sie haben eine Installation mit CD ausgewählt, jedoch wurde kein CDROM-"
-#~ "Laufwerk im System gefunden. Bitte wählen Sie eine andere "
-#~ "Installationsmethode."
-
-#~ msgid "Source URL"
-#~ msgstr "Quell-URL"
-
-#~ msgid ""
-#~ "Enter a host you get the files from.You also must enter a path where the "
-#~ "installer finds the files in."
-#~ msgstr ""
-#~ "Bitte geben Sie einen Server ein, von dem Sie die Installationsdateien "
-#~ "beziehen. Weiterhin müssen Sie einen Pfad eingeben, in dem der Installer "
-#~ "die Dateien auf dem Server findet."
-
-#~ msgid "Path:"
-#~ msgstr "Pfad:"
-
-#~ msgid "Wrong Protocol"
-#~ msgstr "Ungültiges Protokoll"
-
-#~ msgid ""
-#~ "You entered a protocol that is not supported by Pomona. There are only "
-#~ "http:// and ftp:// available."
-#~ msgstr ""
-#~ "Sie haben einen Protokolltyp eingegeben, der nicht von Pomona unterstützt "
-#~ "wird. Unterstützt werden http:// und ftp://."
-
-#, fuzzy
-#~ msgid "Syntax Error"
-#~ msgstr "Fehler"
-
-#~ msgid "The path of the URL must end with a /."
-#~ msgstr "Der Pfad muss mit einem / enden."
-
-#~ msgid ""
-#~ "When we tested your given URL there was an error.\n"
-#~ "\n"
-#~ "%s"
-#~ msgstr ""
-#~ "Bei einem Test der eingegebenen URL trat ein Fehler auf.\n"
-#~ "\n"
-#~ "%s"
-
-#~ msgid "Downloading"
-#~ msgstr "Download"
-
-#~ msgid "Connecting..."
-#~ msgstr "Verbinde..."
-
-#~ msgid "Retrieving %s"
-#~ msgstr "Lade %s"
-
-#~ msgid ""
-#~ "The file %s cannot be opened. This is due to a missing file or perhaps a "
-#~ "corrupt package. Please verify your mirror contains all required "
-#~ "packages, and try using a different one.\n"
-#~ "\n"
-#~ "If you reboot, your system will be left in an inconsistent state that "
-#~ "will likely require reinstallation.\n"
-#~ "\n"
-#~ msgstr ""
-#~ "Die Datei %s konnte nicht geöffnet werden. Es könnte sein, dass diese "
-#~ "garnicht vorhanden oder beschädigt ist. Bitte überprüfen Sie ihren Server "
-#~ "oder nutzen Sie einen anderen.\n"
-#~ "\n"
-#~ "Wenn Sie jetzt neustarten wird das System in einem inkonsistenten Zustand "
-#~ "bleiben und eine Neuinstallation nötig sein.\n"
-#~ "\n"
-
-#, fuzzy
-#~ msgid "Preparing transaction from installation source..."
-#~ msgstr "Starte Textinstallation..."
-
-#, fuzzy
-#~ msgid "Re_boot"
-#~ msgstr "Neustarten"
-
-#, fuzzy
-#~ msgid "_Retry"
-#~ msgstr "Wiederholen"
-
-#, fuzzy
-#~ msgid "Loading %s"
-#~ msgstr "Warnung"
+++ /dev/null
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-02-17 19:28+0100\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=CHARSET\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-#: ../autopart.py:872
-#, python-format
-msgid ""
-"Error resizing partition %s.\n"
-"\n"
-"%s"
-msgstr ""
-
-#: ../autopart.py:875
-#, python-format
-msgid "Start of partition %s was moved when resizing"
-msgstr ""
-
-#: ../autopart.py:967
-msgid "Could not allocate cylinder-based partitions as primary partitions.\n"
-msgstr ""
-
-#: ../autopart.py:972
-msgid "Could not allocate partitions as primary partitions.\n"
-msgstr ""
-
-#: ../autopart.py:977
-msgid "Could not allocate cylinder-based partitions.\n"
-msgstr ""
-
-#: ../autopart.py:1042
-#, python-format
-msgid ""
-"Boot partition %s doesn't belong to a BSD disk label. SRM won't be able to "
-"boot from this partition. Use a partition belonging to a BSD disk label or "
-"change this device disk label to BSD."
-msgstr ""
-
-#: ../autopart.py:1044
-#, python-format
-msgid ""
-"Boot partition %s doesn't belong to a disk with enough free space at its "
-"beginning for the bootloader to live on. Make sure that there's at least 5MB "
-"of free space at the beginning of the disk that contains /boot"
-msgstr ""
-
-#: ../autopart.py:1046
-#, python-format
-msgid ""
-"Boot partition %s isn't a VFAT partition. EFI won't be able to boot from "
-"this partition."
-msgstr ""
-
-#: ../autopart.py:1048
-msgid ""
-"The boot partition must entirely be in the first 4GB of the disk. "
-"OpenFirmware won't be able to boot this installation."
-msgstr ""
-
-#: ../autopart.py:1050
-#, python-format
-msgid ""
-"Boot partition %s is not a Linux filesystem, such as ext3. The system won't "
-"be able to boot from this partition."
-msgstr ""
-
-#: ../autopart.py:1053
-#, python-format
-msgid ""
-"Boot partition %s may not meet booting constraints for your architecture."
-msgstr ""
-
-#: ../autopart.py:1078
-#, python-format
-msgid ""
-"Adding this partition would not leave enough disk space for already "
-"allocated logical volumes in %s."
-msgstr ""
-
-#: ../autopart.py:1231
-msgid "Requested Partition Does Not Exist"
-msgstr ""
-
-#: ../autopart.py:1232
-#, python-format
-msgid ""
-"Unable to locate partition %s to use for %s.\n"
-"\n"
-"Press 'OK' to exit the installer."
-msgstr ""
-
-#: ../autopart.py:1257
-msgid "Requested Raid Device Does Not Exist"
-msgstr ""
-
-#: ../autopart.py:1258
-#, python-format
-msgid ""
-"Unable to locate raid device %s to use for %s.\n"
-"\n"
-"Press 'OK' to exit the installer."
-msgstr ""
-
-#: ../autopart.py:1287
-msgid "Requested Volume Group Does Not Exist"
-msgstr ""
-
-#: ../autopart.py:1288
-#, python-format
-msgid ""
-"Unable to locate volume group %s to use for %s.\n"
-"\n"
-"Press 'OK' to exit the installer."
-msgstr ""
-
-#: ../autopart.py:1325
-msgid "Requested Logical Volume Does Not Exist"
-msgstr ""
-
-#: ../autopart.py:1326
-#, python-format
-msgid ""
-"Unable to locate logical volume %s to use for %s.\n"
-"\n"
-"Press 'OK' to exit the installer."
-msgstr ""
-
-#: ../autopart.py:1460 ../autopart.py:1507
-msgid "Automatic Partitioning Errors"
-msgstr ""
-
-#: ../autopart.py:1461
-#, python-format
-msgid ""
-"The following errors occurred with your partitioning:\n"
-"\n"
-"%s\n"
-"\n"
-"Press 'OK' to exit the installer."
-msgstr ""
-
-#: ../autopart.py:1471
-msgid "Warnings During Automatic Partitioning"
-msgstr ""
-
-#: ../autopart.py:1472
-#, python-format
-msgid ""
-"Following warnings occurred during automatic partitioning:\n"
-"\n"
-"%s"
-msgstr ""
-
-#: ../autopart.py:1486 ../autopart.py:1503
-msgid ""
-"\n"
-"\n"
-"Press 'OK' to exit the installer."
-msgstr ""
-
-#: ../autopart.py:1487 ../tui_partition.py:177
-msgid "Error Partitioning"
-msgstr ""
-
-#: ../autopart.py:1488
-#, python-format
-msgid ""
-"Could not allocate requested partitions: \n"
-"\n"
-"%s.%s"
-msgstr ""
-
-#: ../autopart.py:1505
-msgid ""
-"\n"
-"\n"
-"Press 'OK' to choose a different partitioning option."
-msgstr ""
-
-#: ../autopart.py:1508
-#, python-format
-msgid ""
-"The following errors occurred with your partitioning:\n"
-"\n"
-"%s\n"
-"\n"
-"This can happen if there is not enough space on your hard drive(s) for the "
-"installation. %s"
-msgstr ""
-
-#: ../autopart.py:1519
-msgid "Unrecoverable Error"
-msgstr ""
-
-#: ../autopart.py:1520
-msgid "Your system will now be rebooted."
-msgstr ""
-
-#: ../autopart.py:1623
-msgid ""
-"Automatic Partitioning sets partitions based on the selected installation "
-"type. You also can customize the partitions once they have been created.\n"
-"\n"
-"The manual disk partitioning tool, Disk Druid, allows you to create "
-"partitions in an interactive environment. You can set the file system types, "
-"mount points, partition sizes, and more."
-msgstr ""
-
-#: ../autopart.py:1634
-msgid ""
-"Before automatic partitioning can be set up by the installation program, you "
-"must choose how to use the space on your hard drives."
-msgstr ""
-
-#: ../autopart.py:1639
-msgid "Remove all partitions on this system"
-msgstr ""
-
-#: ../autopart.py:1640
-msgid "Remove all Linux partitions on this system"
-msgstr ""
-
-#: ../autopart.py:1641
-msgid "Keep all partitions and use existing free space"
-msgstr ""
-
-#: ../bootloader.py:697
-msgid "Bootloader"
-msgstr ""
-
-#: ../bootloader.py:697
-msgid "Installing bootloader..."
-msgstr ""
-
-#: ../bootloader.py:746 ../partedUtils.py:328 ../partedUtils.py:851
-#: ../partedUtils.py:979 ../tui_bootloader.py:119 ../tui_bootloader.py:439
-#: ../tui_partition.py:182
-msgid "Warning"
-msgstr ""
-
-#: ../bootloader.py:747
-msgid ""
-"No kernel packages were installed on your system. Your boot loader "
-"configuration will not be changed."
-msgstr ""
-
-#: ../constants.py:61
-msgid ""
-"An unhandled exception has occurred. This is most likely a bug. Please "
-"save a copy of the detailed exception and file a bug report"
-msgstr ""
-
-#: ../constants.py:67
-msgid " with the provider of this software."
-msgstr ""
-
-#: ../constants.py:71
-#, python-format
-msgid " against pomona at %s"
-msgstr ""
-
-#: ../constants.py:89 ../installer.py:93 ../tui_confirm.py:28
-#: ../tui_network.py:65 ../tui_network.py:74 ../tui.py:224 ../tui.py:390
-msgid "OK"
-msgstr ""
-
-#: ../constants.py:93 ../partIntfHelpers.py:245 ../partIntfHelpers.py:536
-#: ../tui_bootloader.py:194 ../tui.py:103 ../tui.py:104 ../tui.py:393
-msgid "Cancel"
-msgstr ""
-
-#: ../constants.py:97 ../partitions.py:130 ../partitions.py:260
-#: ../tui_confirm.py:28 ../tui_confirm.py:30
-msgid "Back"
-msgstr ""
-
-#: ../constants.py:101 ../tui_bootloader.py:67 ../tui.py:388
-msgid "Yes"
-msgstr ""
-
-#: ../constants.py:105 ../tui_bootloader.py:67 ../tui.py:389
-msgid "No"
-msgstr ""
-
-#: ../constants.py:109 ../tui_bootloader.py:270 ../tui_partition.py:849
-msgid "Edit"
-msgstr ""
-
-#: ../fsset.py:497
-msgid "Checking"
-msgstr ""
-
-#: ../fsset.py:498
-#, python-format
-msgid "Checking filesystem on %s..."
-msgstr ""
-
-#: ../fsset.py:509 ../fsset.py:944
-msgid "Resizing"
-msgstr ""
-
-#: ../fsset.py:510 ../fsset.py:945
-#, python-format
-msgid "Resizing filesystem on %s..."
-msgstr ""
-
-#: ../fsset.py:653 ../fsset.py:1536 ../fsset.py:1567 ../fsset.py:1643
-#: ../fsset.py:1711 ../fsset.py:1761 ../fsset.py:1850 ../fsset.py:1863
-#: ../partIntfHelpers.py:413
-msgid "Error"
-msgstr ""
-
-#: ../fsset.py:654
-#, python-format
-msgid ""
-"An error occurred migrating %s to ext3. It is possible to continue without "
-"migrating this file system if desired.\n"
-"\n"
-"Would you like to continue without migrating %s?"
-msgstr ""
-
-#: ../fsset.py:1413
-msgid "RAID Device"
-msgstr ""
-
-#: ../fsset.py:1416
-msgid "First sector of boot partition"
-msgstr ""
-
-#: ../fsset.py:1417
-msgid "Master Boot Record (MBR)"
-msgstr ""
-
-#: ../fsset.py:1537
-#, python-format
-msgid ""
-"An error occurred trying to initialize swap on device %s. This problem is "
-"serious, and the install cannot continue.\n"
-"\n"
-"Press <Enter> to exit the installer."
-msgstr ""
-
-#: ../fsset.py:1566
-msgid "Skip"
-msgstr ""
-
-#: ../fsset.py:1566 ../fsset.py:1830 ../fsset.py:2581
-msgid "_Exit installer"
-msgstr ""
-
-#: ../fsset.py:1587
-#, python-format
-msgid ""
-"The swap device:\n"
-"\n"
-" /dev/%s\n"
-"\n"
-"is a version 0 Linux swap partition. If you want to use this device, you "
-"must reformat as a version 1 Linux swap partition. If you skip it, the "
-"installer will ignore it during the installation."
-msgstr ""
-
-#: ../fsset.py:1594
-msgid "Reformat"
-msgstr ""
-
-#: ../fsset.py:1598
-#, python-format
-msgid ""
-"The swap device:\n"
-"\n"
-" /dev/%s\n"
-"\n"
-"in your /etc/fstab file is currently in use as a software suspend partition, "
-"which means your system is hibernating. To perform an upgrade, please shut "
-"down your system rather than hibernating it."
-msgstr ""
-
-#: ../fsset.py:1606
-#, python-format
-msgid ""
-"The swap device:\n"
-"\n"
-" /dev/%s\n"
-"\n"
-"in your /etc/fstab file is currently in use as a software suspend partition, "
-"which means your system is hibernating. If you are performing a new install, "
-"make sure the installer is set to format all swap partitions."
-msgstr ""
-
-#: ../fsset.py:1616
-msgid ""
-"\n"
-"\n"
-"Choose Skip if you want the installer to ignore this partition during the "
-"upgrade. Choose Format to reformat the partition as swap space."
-msgstr ""
-
-#: ../fsset.py:1621
-msgid "Format"
-msgstr ""
-
-#: ../fsset.py:1627
-#, python-format
-msgid ""
-"Error enabling swap device %s: %s\n"
-"\n"
-"Devices in /etc/fstab should be specified by label, not by device name.\n"
-"\n"
-"Press OK to exit the installer."
-msgstr ""
-
-#: ../fsset.py:1632
-#, python-format
-msgid ""
-"Error enabling swap device %s: %s\n"
-"\n"
-"The /etc/fstab on your upgrade partition does not reference a valid swap "
-"partition.\n"
-"\n"
-"Press OK to exit the installer"
-msgstr ""
-
-#: ../fsset.py:1638
-#, python-format
-msgid ""
-"Error enabling swap device %s: %s\n"
-"\n"
-"This most likely means this swap partition has not been initialized.\n"
-"\n"
-"Press OK to exit the installer."
-msgstr ""
-
-#: ../fsset.py:1712
-#, python-format
-msgid ""
-"An error occurred trying to format %s. This problem is serious, and the "
-"install cannot continue.\n"
-"\n"
-"Press <Enter> to exit the installer."
-msgstr ""
-
-#: ../fsset.py:1762
-#, python-format
-msgid ""
-"An error occurred trying to migrate %s. This problem is serious, and the "
-"install cannot continue.\n"
-"\n"
-"Press <Enter> to exit the installer."
-msgstr ""
-
-#: ../fsset.py:1798 ../fsset.py:1807
-msgid "Invalid mount point"
-msgstr ""
-
-#: ../fsset.py:1799
-#, python-format
-msgid ""
-"An error occurred when trying to create %s. Some element of this path is "
-"not a directory. This is a fatal error and the install cannot continue.\n"
-"\n"
-"Press <Enter> to exit the installer."
-msgstr ""
-
-#: ../fsset.py:1808
-#, python-format
-msgid ""
-"An error occurred when trying to create %s: %s. This is a fatal error and "
-"the install cannot continue.\n"
-"\n"
-"Press <Enter> to exit the installer."
-msgstr ""
-
-#: ../fsset.py:1822
-msgid "Unable to mount filesystem"
-msgstr ""
-
-#: ../fsset.py:1823
-#, python-format
-msgid ""
-"An error occurred mounting device %s as %s. You may continue installation, "
-"but there may be problems."
-msgstr ""
-
-#: ../fsset.py:1831 ../partedUtils.py:982
-msgid "_Continue"
-msgstr ""
-
-#: ../fsset.py:1839
-#, python-format
-msgid ""
-"Error mounting device %s as %s: %s\n"
-"\n"
-"Devices in /etc/fstab should be specified by label or UUID, not by device "
-"name.\n"
-"\n"
-"Press OK to exit the installer."
-msgstr ""
-
-#: ../fsset.py:1846
-#, python-format
-msgid ""
-"Error mounting device %s as %s: %s\n"
-"\n"
-"Press OK to exit the installer."
-msgstr ""
-
-#: ../fsset.py:1864
-msgid ""
-"Error finding / entry.\n"
-"\n"
-"This is most likely means that your fstab is incorrect.\n"
-"\n"
-"Press OK to exit the installer."
-msgstr ""
-
-#: ../fsset.py:2573
-msgid "Duplicate Labels"
-msgstr ""
-
-#: ../fsset.py:2574
-#, python-format
-msgid ""
-"Multiple devices on your system are labelled %s. Labels across devices must "
-"be unique for your system to function properly.\n"
-"\n"
-"Please fix this problem and restart the installation process."
-msgstr ""
-
-#: ../fsset.py:2739
-msgid "Formatting"
-msgstr ""
-
-#: ../fsset.py:2740
-#, python-format
-msgid "Formatting %s file system..."
-msgstr ""
-
-#: ../installer.py:88
-msgid "Fatal Error"
-msgstr ""
-
-#: ../installer.py:89
-#, python-format
-msgid ""
-"You do not have enough RAM to install %s on this machine.\n"
-"\n"
-"Press <return> to reboot your system.\n"
-msgstr ""
-
-#: ../installer.py:173
-msgid "Starting text installation..."
-msgstr ""
-
-#: ../keyboard_models.py:48
-msgid "keyboard|Arabic (azerty)"
-msgstr ""
-
-#: ../keyboard_models.py:51
-msgid "keyboard|Arabic (azerty/digits)"
-msgstr ""
-
-#: ../keyboard_models.py:54
-msgid "keyboard|Arabic (digits)"
-msgstr ""
-
-#: ../keyboard_models.py:57
-msgid "keyboard|Arabic (qwerty)"
-msgstr ""
-
-#: ../keyboard_models.py:60
-msgid "keyboard|Arabic (qwerty/digits)"
-msgstr ""
-
-#: ../keyboard_models.py:63
-msgid "keyboard|Belgian (be-latin1)"
-msgstr ""
-
-#: ../keyboard_models.py:66
-msgid "keyboard|Bengali (Inscript)"
-msgstr ""
-
-#: ../keyboard_models.py:69
-msgid "keyboard|Bengali (Probhat)"
-msgstr ""
-
-#: ../keyboard_models.py:72
-msgid "keyboard|Bulgarian"
-msgstr ""
-
-#: ../keyboard_models.py:75
-msgid "keyboard|Bulgarian (Phonetic)"
-msgstr ""
-
-#: ../keyboard_models.py:78
-msgid "keyboard|Brazilian (ABNT2)"
-msgstr ""
-
-#: ../keyboard_models.py:81
-msgid "keyboard|French Canadian"
-msgstr ""
-
-#: ../keyboard_models.py:84
-msgid "keyboard|Croatian"
-msgstr ""
-
-#: ../keyboard_models.py:87
-msgid "keyboard|Czech"
-msgstr ""
-
-#: ../keyboard_models.py:90
-msgid "keyboard|Czech (qwerty)"
-msgstr ""
-
-#: ../keyboard_models.py:93
-msgid "keyboard|German"
-msgstr ""
-
-#: ../keyboard_models.py:96
-msgid "keyboard|German (latin1)"
-msgstr ""
-
-#: ../keyboard_models.py:99
-msgid "keyboard|German (latin1 w/ no deadkeys)"
-msgstr ""
-
-#: ../keyboard_models.py:102
-msgid "keyboard|Devanagari (Inscript)"
-msgstr ""
-
-#: ../keyboard_models.py:105
-msgid "keyboard|Dvorak"
-msgstr ""
-
-#: ../keyboard_models.py:108
-msgid "keyboard|Danish"
-msgstr ""
-
-#: ../keyboard_models.py:111
-msgid "keyboard|Danish (latin1)"
-msgstr ""
-
-#: ../keyboard_models.py:114
-msgid "keyboard|Spanish"
-msgstr ""
-
-#: ../keyboard_models.py:117
-msgid "keyboard|Estonian"
-msgstr ""
-
-#: ../keyboard_models.py:120
-msgid "keyboard|Finnish"
-msgstr ""
-
-#: ../keyboard_models.py:123
-msgid "keyboard|Finnish (latin1)"
-msgstr ""
-
-#: ../keyboard_models.py:126
-msgid "keyboard|French"
-msgstr ""
-
-#: ../keyboard_models.py:129
-msgid "keyboard|French (latin9)"
-msgstr ""
-
-#: ../keyboard_models.py:132
-msgid "keyboard|French (latin1)"
-msgstr ""
-
-#: ../keyboard_models.py:135
-msgid "keyboard|French (pc)"
-msgstr ""
-
-#: ../keyboard_models.py:138
-msgid "keyboard|Swiss French"
-msgstr ""
-
-#: ../keyboard_models.py:141
-msgid "keyboard|Swiss French (latin1)"
-msgstr ""
-
-#: ../keyboard_models.py:144
-msgid "keyboard|Greek"
-msgstr ""
-
-#: ../keyboard_models.py:147
-msgid "keyboard|Gujarati (Inscript)"
-msgstr ""
-
-#: ../keyboard_models.py:150
-msgid "keyboard|Punjabi (Inscript)"
-msgstr ""
-
-#: ../keyboard_models.py:153
-msgid "keyboard|Hungarian"
-msgstr ""
-
-#: ../keyboard_models.py:156
-msgid "keyboard|Hungarian (101 key)"
-msgstr ""
-
-#: ../keyboard_models.py:159
-msgid "keyboard|Icelandic"
-msgstr ""
-
-#: ../keyboard_models.py:162
-msgid "keyboard|Italian"
-msgstr ""
-
-#: ../keyboard_models.py:165
-msgid "keyboard|Italian (IBM)"
-msgstr ""
-
-#: ../keyboard_models.py:168
-msgid "keyboard|Italian (it2)"
-msgstr ""
-
-#: ../keyboard_models.py:171
-msgid "keyboard|Japanese"
-msgstr ""
-
-#: ../keyboard_models.py:174
-msgid "keyboard|Korean"
-msgstr ""
-
-#: ../keyboard_models.py:177
-msgid "keyboard|Latin American"
-msgstr ""
-
-#: ../keyboard_models.py:180
-msgid "keyboard|Macedonian"
-msgstr ""
-
-#: ../keyboard_models.py:183
-msgid "keyboard|Dutch"
-msgstr ""
-
-#: ../keyboard_models.py:186
-msgid "keyboard|Norwegian"
-msgstr ""
-
-#: ../keyboard_models.py:189
-msgid "keyboard|Polish"
-msgstr ""
-
-#: ../keyboard_models.py:192
-msgid "keyboard|Portuguese"
-msgstr ""
-
-#: ../keyboard_models.py:195
-msgid "keyboard|Romanian"
-msgstr ""
-
-#: ../keyboard_models.py:198
-msgid "keyboard|Russian"
-msgstr ""
-
-#: ../keyboard_models.py:201
-msgid "keyboard|Serbian"
-msgstr ""
-
-#: ../keyboard_models.py:204
-msgid "keyboard|Serbian (latin)"
-msgstr ""
-
-#: ../keyboard_models.py:207
-msgid "keyboard|Swedish"
-msgstr ""
-
-#: ../keyboard_models.py:210
-msgid "keyboard|Swiss German"
-msgstr ""
-
-#: ../keyboard_models.py:213
-msgid "keyboard|Swiss German (latin1)"
-msgstr ""
-
-#: ../keyboard_models.py:216
-msgid "keyboard|Slovak (qwerty)"
-msgstr ""
-
-#: ../keyboard_models.py:219
-msgid "keyboard|Slovenian"
-msgstr ""
-
-#: ../keyboard_models.py:222
-msgid "keyboard|Tamil (Inscript)"
-msgstr ""
-
-#: ../keyboard_models.py:225
-msgid "keyboard|Tamil (Typewriter)"
-msgstr ""
-
-#: ../keyboard_models.py:228
-msgid "keyboard|Turkish"
-msgstr ""
-
-#: ../keyboard_models.py:231
-msgid "keyboard|United Kingdom"
-msgstr ""
-
-#: ../keyboard_models.py:234
-msgid "keyboard|Ukrainian"
-msgstr ""
-
-#: ../keyboard_models.py:237
-msgid "keyboard|U.S. International"
-msgstr ""
-
-#: ../keyboard_models.py:240
-msgid "keyboard|U.S. English"
-msgstr ""
-
-#: ../network.py:31
-msgid "IP address is missing."
-msgstr ""
-
-#: ../network.py:35
-msgid ""
-"IPv4 addresses must contain four numbers between 0 and 255, separated by "
-"periods."
-msgstr ""
-
-#: ../network.py:38
-#, python-format
-msgid "'%s' is not a valid IPv6 address."
-msgstr ""
-
-#: ../network.py:40
-#, python-format
-msgid "'%s' is an invalid IP address."
-msgstr ""
-
-#: ../network.py:52
-msgid "Hostname must be 255 or fewer characters in length."
-msgstr ""
-
-#: ../network.py:58
-msgid ""
-"Hostname must start with a valid character in the ranges 'a-z', 'A-Z', or '0-"
-"9'"
-msgstr ""
-
-#: ../network.py:63
-msgid ""
-"Hostnames can only contain the characters 'a-z', 'A-Z', '0-9', '-', or '.'"
-msgstr ""
-
-#: ../packages.py:113
-msgid "Warning! This is pre-release software!"
-msgstr ""
-
-#: ../packages.py:114
-#, python-format
-msgid ""
-"Thank you for downloading this pre-release of %s.\n"
-"\n"
-"This is not a final release and is not intended for use on production "
-"systems. The purpose of this release is to collect feedback from testers, "
-"and it is not suitable for day to day usage.\n"
-"\n"
-"To report feedback, please visit:\n"
-"\n"
-" %s\n"
-"\n"
-"and file a report against '%s'.\n"
-msgstr ""
-
-#: ../packages.py:127
-msgid "_Exit"
-msgstr ""
-
-#: ../packages.py:127
-msgid "_Install anyway"
-msgstr ""
-
-#: ../packages.py:130
-msgid "Your system will now be rebooted..."
-msgstr ""
-
-#: ../packages.py:131 ../tui_confirm.py:37
-msgid "_Back"
-msgstr ""
-
-#: ../packages.py:131 ../partedUtils.py:981 ../tui_confirm.py:37
-msgid "_Reboot"
-msgstr ""
-
-#: ../packages.py:132
-msgid "Rebooting System"
-msgstr ""
-
-#: ../pakfireinstall.py:47
-#, python-format
-msgid "%s MB"
-msgstr ""
-
-#: ../pakfireinstall.py:50
-#, python-format
-msgid "%s KB"
-msgstr ""
-
-#: ../pakfireinstall.py:53
-#, python-format
-msgid "%s Byte"
-msgstr ""
-
-#: ../pakfireinstall.py:55
-#, python-format
-msgid "%s Bytes"
-msgstr ""
-
-#: ../pakfireinstall.py:134
-msgid "Base system"
-msgstr ""
-
-#: ../pakfireinstall.py:134
-msgid "Installing base system..."
-msgstr ""
-
-#: ../pakfireinstall.py:171
-msgid "Install Starting"
-msgstr ""
-
-#: ../pakfireinstall.py:172
-msgid "Starting install process. This may take several minutes..."
-msgstr ""
-
-#: ../pakfireinstall.py:183
-msgid "Post Install"
-msgstr ""
-
-#: ../pakfireinstall.py:184
-msgid "Performing post install configuration..."
-msgstr ""
-
-#: ../pakfireinstall.py:215
-msgid "Symmetric multiprocessing"
-msgstr ""
-
-#: ../pakfireinstall.py:216
-msgid "Xen guest"
-msgstr ""
-
-#: ../pakfireinstall.py:226
-msgid "Normal Boot"
-msgstr ""
-
-#: ../pakfireinstall.py:233
-msgid "Installation Progress"
-msgstr ""
-
-#: ../partedUtils.py:239 ../tui_partition.py:408
-msgid "Foreign"
-msgstr ""
-
-#: ../partedUtils.py:329
-#, python-format
-msgid ""
-"/dev/%s currently has a %s partition layout. To use this drive for the "
-"installation of %s, it must be re-initialized, causing the loss of ALL DATA "
-"on this drive.\n"
-"\n"
-"Would you like to re-initialize this drive?"
-msgstr ""
-
-#: ../partedUtils.py:338
-msgid "_Ignore drive"
-msgstr ""
-
-#: ../partedUtils.py:339
-msgid "_Re-initialize drive"
-msgstr ""
-
-#: ../partedUtils.py:842
-#, python-format
-msgid ""
-"The partition table on device %s (%s %-0.f MB) was unreadable.\n"
-"\n"
-"To create new partitions it must be initialized, causing the loss of ALL "
-"DATA on this drive.\n"
-"\n"
-"This operation will override any previous installation choices about which "
-"drives to ignore.\n"
-"\n"
-"Would you like to initialize this drive, erasing ALL DATA?"
-msgstr ""
-
-#: ../partedUtils.py:972
-#, python-format
-msgid ""
-"The drive /dev/%s has more than 15 partitions on it. The SCSI subsystem in "
-"the Linux kernel does not allow for more than 15 partitons at this time. "
-"You will not be able to make changes to the partitioning of this disk or use "
-"any partitions beyond /dev/%s15 in %s"
-msgstr ""
-
-#: ../partedUtils.py:1056
-msgid "No Drives Found"
-msgstr ""
-
-#: ../partedUtils.py:1057
-msgid ""
-"An error has occurred - no valid devices were found on which to create new "
-"file systems. Please check your hardware for the cause of this problem."
-msgstr ""
-
-#: ../partIntfHelpers.py:43
-msgid "Please enter a volume group name."
-msgstr ""
-
-#: ../partIntfHelpers.py:47
-msgid "Volume Group Names must be less than 128 characters"
-msgstr ""
-
-#: ../partIntfHelpers.py:50
-#, python-format
-msgid "Error - the volume group name %s is not valid."
-msgstr ""
-
-#: ../partIntfHelpers.py:55
-msgid ""
-"Error - the volume group name contains illegal characters or spaces. "
-"Acceptable characters are letters, digits, '.' or '_'."
-msgstr ""
-
-#: ../partIntfHelpers.py:65
-msgid "Please enter a logical volume name."
-msgstr ""
-
-#: ../partIntfHelpers.py:69
-msgid "Logical Volume Names must be less than 128 characters"
-msgstr ""
-
-#: ../partIntfHelpers.py:73
-#, python-format
-msgid "Error - the logical volume name %s is not valid."
-msgstr ""
-
-#: ../partIntfHelpers.py:79
-msgid ""
-"Error - the logical volume name contains illegal characters or spaces. "
-"Acceptable characters are letters, digits, '.' or '_'."
-msgstr ""
-
-#: ../partIntfHelpers.py:103
-#, python-format
-msgid ""
-"The mount point %s is invalid. Mount points must start with '/' and cannot "
-"end with '/', and must contain printable characters and no spaces."
-msgstr ""
-
-#: ../partIntfHelpers.py:110
-msgid "Please specify a mount point for this partition."
-msgstr ""
-
-#: ../partIntfHelpers.py:120
-#, python-format
-msgid "This partition is part of the RAID device /dev/md%s."
-msgstr ""
-
-#: ../partIntfHelpers.py:123
-msgid "This partition is part of a RAID device."
-msgstr ""
-
-#: ../partIntfHelpers.py:128
-#, python-format
-msgid "This partition is part of the LVM volume group '%s'."
-msgstr ""
-
-#: ../partIntfHelpers.py:131
-msgid "This partition is part of a LVM volume group."
-msgstr ""
-
-#: ../partIntfHelpers.py:146 ../partIntfHelpers.py:154
-#: ../partIntfHelpers.py:161 ../partIntfHelpers.py:171
-#: ../partIntfHelpers.py:195
-msgid "Unable To Delete"
-msgstr ""
-
-#: ../partIntfHelpers.py:147
-msgid "You must first select a partition to delete."
-msgstr ""
-
-#: ../partIntfHelpers.py:155
-msgid "You cannot delete free space."
-msgstr ""
-
-#: ../partIntfHelpers.py:162
-msgid "You cannot delete a partition of a LDL formatted DASD."
-msgstr ""
-
-#: ../partIntfHelpers.py:172
-#, python-format
-msgid ""
-"You cannot delete this partition, as it is an extended partition which "
-"contains %s"
-msgstr ""
-
-#: ../partIntfHelpers.py:190
-msgid "This partition is holding the data for the hard drive install."
-msgstr ""
-
-#: ../partIntfHelpers.py:196
-msgid ""
-"You cannot delete this partition:\n"
-"\n"
-msgstr ""
-
-#: ../partIntfHelpers.py:241 ../partIntfHelpers.py:535
-msgid "Confirm Delete"
-msgstr ""
-
-#: ../partIntfHelpers.py:242
-#, python-format
-msgid "You are about to delete all partitions on the device '/dev/%s'."
-msgstr ""
-
-#: ../partIntfHelpers.py:245 ../partIntfHelpers.py:536
-msgid "_Delete"
-msgstr ""
-
-#: ../partIntfHelpers.py:302
-msgid "Notice"
-msgstr ""
-
-#: ../partIntfHelpers.py:303
-#, python-format
-msgid ""
-"The following partitions were not deleted because they are in use:\n"
-"\n"
-"%s"
-msgstr ""
-
-#: ../partIntfHelpers.py:319 ../partIntfHelpers.py:332
-#: ../partIntfHelpers.py:358 ../partIntfHelpers.py:369
-msgid "Unable To Edit"
-msgstr ""
-
-#: ../partIntfHelpers.py:320
-msgid "You must select a partition to edit"
-msgstr ""
-
-#: ../partIntfHelpers.py:332 ../partIntfHelpers.py:370
-msgid ""
-"You cannot edit this partition:\n"
-"\n"
-msgstr ""
-
-#: ../partIntfHelpers.py:359
-#, python-format
-msgid ""
-"You cannot edit this partition, as it is an extended partition which "
-"contains %s"
-msgstr ""
-
-#: ../partIntfHelpers.py:391
-msgid "Format as Swap?"
-msgstr ""
-
-#: ../partIntfHelpers.py:392
-#, python-format
-msgid ""
-"/dev/%s has a partition type of 0x82 (Linux swap) but does not appear to be "
-"formatted as a Linux swap partition.\n"
-"\n"
-"Would you like to format this partition as a swap partition?"
-msgstr ""
-
-#: ../partIntfHelpers.py:412
-#, python-format
-msgid "You need to select at least one hard drive to install %s."
-msgstr ""
-
-#: ../partIntfHelpers.py:417
-msgid ""
-"You have chosen to use a pre-existing partition for this installation "
-"without formatting it. We recommend that you format this partition to make "
-"sure files from a previous operating system installation do not cause "
-"problems with this installation of Linux. However, if this partition "
-"contains files that you need to keep, such as home directories, then "
-"continue without formatting this partition."
-msgstr ""
-
-#: ../partIntfHelpers.py:425
-msgid "Format?"
-msgstr ""
-
-#: ../partIntfHelpers.py:425
-msgid "_Modify Partition"
-msgstr ""
-
-#: ../partIntfHelpers.py:425
-msgid "Do _Not Format"
-msgstr ""
-
-#: ../partIntfHelpers.py:433
-msgid "Error with Partitioning"
-msgstr ""
-
-#: ../partIntfHelpers.py:434
-#, python-format
-msgid ""
-"The following critical errors exist with your requested partitioning scheme. "
-"These errors must be corrected prior to continuing with your install of %s.\n"
-"\n"
-"%s"
-msgstr ""
-
-#: ../partIntfHelpers.py:448
-msgid "Partitioning Warning"
-msgstr ""
-
-#: ../partIntfHelpers.py:449
-#, python-format
-msgid ""
-"The following warnings exist with your requested partition scheme.\n"
-"\n"
-"%s\n"
-"\n"
-"Would you like to continue with your requested partitioning scheme?"
-msgstr ""
-
-#: ../partIntfHelpers.py:463
-msgid ""
-"The following pre-existing partitions have been selected to be formatted, "
-"destroying all data."
-msgstr ""
-
-#: ../partIntfHelpers.py:466
-msgid ""
-"Select 'Yes' to continue and format these partitions, or 'No' to go back and "
-"change these settings."
-msgstr ""
-
-#: ../partIntfHelpers.py:472
-msgid "Format Warning"
-msgstr ""
-
-#: ../partIntfHelpers.py:520
-#, python-format
-msgid ""
-"You are about to delete the volume group \"%s\".\n"
-"\n"
-"ALL logical volumes in this volume group will be lost!"
-msgstr ""
-
-#: ../partIntfHelpers.py:524
-#, python-format
-msgid "You are about to delete the logical volume \"%s\"."
-msgstr ""
-
-#: ../partIntfHelpers.py:527
-msgid "You are about to delete a RAID device."
-msgstr ""
-
-#: ../partIntfHelpers.py:530
-#, python-format
-msgid "You are about to delete the /dev/%s partition."
-msgstr ""
-
-#: ../partIntfHelpers.py:533
-msgid "The partition you selected will be deleted."
-msgstr ""
-
-#: ../partIntfHelpers.py:543
-msgid "Confirm Reset"
-msgstr ""
-
-#: ../partIntfHelpers.py:544
-msgid ""
-"Are you sure you want to reset the partition table to its original state?"
-msgstr ""
-
-#: ../partitioning.py:36 ../partitions.py:81
-msgid "Installation cannot continue."
-msgstr ""
-
-#: ../partitioning.py:37 ../partitions.py:82
-msgid ""
-"The partitioning options you have chosen have already been activated. You "
-"can no longer return to the disk editing screen. Would you like to continue "
-"with the installation process?"
-msgstr ""
-
-#: ../partitioning.py:65
-msgid "Low Memory"
-msgstr ""
-
-#: ../partitioning.py:66
-msgid ""
-"As you don't have much memory in this machine, we need to turn on swap space "
-"immediately. To do this we'll have to write your new partition table to the "
-"disk immediately. Is that OK?"
-msgstr ""
-
-#: ../partitions.py:122
-msgid "Encrypt device?"
-msgstr ""
-
-#: ../partitions.py:123
-msgid ""
-"You specified block device encryption should be enabled, but you have not "
-"supplied a passphrase. If you do not go back and provide a passphrase, block "
-"device encryption will be disabled."
-msgstr ""
-
-#: ../partitions.py:130 ../partitions.py:260
-msgid "Continue"
-msgstr ""
-
-#: ../partitions.py:151
-msgid "Writing partitioning to disk"
-msgstr ""
-
-#: ../partitions.py:152
-msgid ""
-"The partitioning options you have selected will now be written to disk. Any "
-"data on deleted or reformatted partitions will be lost."
-msgstr ""
-
-#: ../partitions.py:157
-msgid "Go _back"
-msgstr ""
-
-#: ../partitions.py:158
-msgid "_Write changes to disk"
-msgstr ""
-
-#: ../partitions.py:265
-msgid "Confirm"
-msgstr ""
-
-#: ../partitions.py:266
-#, python-format
-msgid ""
-"Are you sure you want to skip entering a passphrase for device %s?\n"
-"\n"
-"If you skip this step the device's contents will not be available during "
-"installation."
-msgstr ""
-
-#: ../partitions.py:1077
-#, python-format
-msgid ""
-"You have not defined a root partition (/), which is required for "
-"installation of %s to continue."
-msgstr ""
-
-#: ../partitions.py:1082
-#, python-format
-msgid ""
-"Your root partition is less than 250 megabytes which is usually too small to "
-"install %s."
-msgstr ""
-
-#: ../partitions.py:1108
-#, python-format
-msgid ""
-"Your %s partition is less than %s megabytes which is lower than recommended "
-"for a normal %s install."
-msgstr ""
-
-#: ../partitions.py:1142
-msgid ""
-"Installing on a USB device. This may or may not produce a working system."
-msgstr ""
-
-#: ../partitions.py:1145
-msgid ""
-"Installing on a FireWire device. This may or may not produce a working "
-"system."
-msgstr ""
-
-#: ../partitions.py:1155
-msgid "Bootable partitions can only be on RAID1 devices."
-msgstr ""
-
-#: ../partitions.py:1160
-msgid "Bootable partitions cannot be on a logical volume."
-msgstr ""
-
-#: ../partitions.py:1166
-msgid "Bootable partitions cannot be on a RAID device."
-msgstr ""
-
-#: ../partitions.py:1171 ../partitions.py:1177
-#, python-format
-msgid "Bootable partitions cannot be on an %s filesystem."
-msgstr ""
-
-#: ../partitions.py:1181
-msgid "Bootable partitions cannot be on an encrypted block device"
-msgstr ""
-
-#: ../partitions.py:1185
-msgid ""
-"You have not specified a swap partition. Although not strictly required in "
-"all cases, it will significantly improve performance for most installations."
-msgstr ""
-
-#: ../partitions.py:1192
-#, python-format
-msgid ""
-"You have specified more than 32 swap devices. The kernel for %s only "
-"supports 32 swap devices."
-msgstr ""
-
-#: ../partitions.py:1203
-#, python-format
-msgid ""
-"You have allocated less swap space (%dM) than available RAM (%dM) on your "
-"system. This could negatively impact performance."
-msgstr ""
-
-#: ../partitions.py:1508
-msgid "the partition in use by the installer."
-msgstr ""
-
-#: ../partitions.py:1511
-msgid "a partition which is a member of a RAID array."
-msgstr ""
-
-#: ../partitions.py:1514
-msgid "a partition which is a member of a LVM Volume Group."
-msgstr ""
-
-#: ../partRequests.py:275 ../partRequests.py:278
-#, python-format
-msgid "The mount point %s must be formatted during live CD installs."
-msgstr ""
-
-#: ../partRequests.py:284
-#, python-format
-msgid ""
-"This mount point is invalid. The %s directory must be on the / file system."
-msgstr ""
-
-#: ../partRequests.py:287
-#, python-format
-msgid ""
-"The mount point %s cannot be used. It must be a symbolic link for proper "
-"system operation. Please select a different mount point."
-msgstr ""
-
-#: ../partRequests.py:296
-msgid "This mount point must be on a linux file system."
-msgstr ""
-
-#: ../partRequests.py:317
-#, python-format
-msgid ""
-"The mount point \"%s\" is already in use, please choose a different mount "
-"point."
-msgstr ""
-
-#: ../partRequests.py:331
-#, python-format
-msgid ""
-"The size of the %s partition (%10.2f MB) exceeds the maximum size of %10.2f "
-"MB."
-msgstr ""
-
-#: ../partRequests.py:539
-#, python-format
-msgid ""
-"The size of the requested partition (size = %s MB) exceeds the maximum size "
-"of %s MB."
-msgstr ""
-
-#: ../partRequests.py:544
-#, python-format
-msgid "The size of the requested partition is negative! (size = %s MB)"
-msgstr ""
-
-#: ../partRequests.py:548
-msgid "Partitions can't start below the first cylinder."
-msgstr ""
-
-#: ../partRequests.py:551
-msgid "Partitions can't end on a negative cylinder."
-msgstr ""
-
-#: ../partRequests.py:753
-msgid "No members in RAID request, or not RAID level specified."
-msgstr ""
-
-#: ../partRequests.py:758
-#, python-format
-msgid "A RAID device of type %s requires at least %s members."
-msgstr ""
-
-#: ../partRequests.py:767
-#, python-format
-msgid ""
-"This RAID device can have a maximum of %s spares. To have more spares you "
-"will need to add members to the RAID device."
-msgstr ""
-
-#: ../partRequests.py:1033
-msgid ""
-"Logical volume size must be larger than the volume group's physical extent "
-"size."
-msgstr ""
-
-#: ../tui_bootloader.py:27
-msgid "Which boot loader would you like to use?"
-msgstr ""
-
-#: ../tui_bootloader.py:37
-msgid "Use GRUB Boot Loader"
-msgstr ""
-
-#: ../tui_bootloader.py:38
-msgid "No Boot Loader"
-msgstr ""
-
-#: ../tui_bootloader.py:41 ../tui_bootloader.py:103 ../tui_bootloader.py:161
-#: ../tui_bootloader.py:278 ../tui_bootloader.py:383
-msgid "Boot Loader Configuration"
-msgstr ""
-
-#: ../tui_bootloader.py:58
-msgid "Skip Boot Loader"
-msgstr ""
-
-#: ../tui_bootloader.py:59
-msgid ""
-"You have elected not to install any boot loader, which is not recommended "
-"unless you have an advanced need. Booting your system into Linux directly "
-"from the hard drive almost always requires a boot loader.\n"
-"\n"
-"Are you sure you want to skip boot loader installation?"
-msgstr ""
-
-#: ../tui_bootloader.py:88
-msgid ""
-"A few systems need to pass special options to the kernel at boot time to "
-"function properly. If you need to pass boot options to the kernel, enter "
-"them now. If you don't need any or aren't sure, leave this blank."
-msgstr ""
-
-#: ../tui_bootloader.py:97
-msgid "Force use of LBA32 (not normally required)"
-msgstr ""
-
-#: ../tui_bootloader.py:120
-msgid ""
-"If LBA32 is not supported by your system's BIOS, forcing its use can prevent "
-"your machine from booting.\n"
-"\n"
-"Would you like to continue and force LBA32 mode?"
-msgstr ""
-
-#: ../tui_bootloader.py:162
-msgid "Where do you want to install the boot loader?"
-msgstr ""
-
-#: ../tui_bootloader.py:188 ../tui_bootloader.py:255 ../tui_partition.py:844
-msgid "Device"
-msgstr ""
-
-#: ../tui_bootloader.py:189 ../tui_bootloader.py:255
-msgid "Boot label"
-msgstr ""
-
-#: ../tui_bootloader.py:193
-msgid "Clear"
-msgstr ""
-
-#: ../tui_bootloader.py:201
-msgid "Edit Boot Label"
-msgstr ""
-
-#: ../tui_bootloader.py:219 ../tui_bootloader.py:224
-msgid "Invalid Boot Label"
-msgstr ""
-
-#: ../tui_bootloader.py:220
-msgid "Boot label may not be empty."
-msgstr ""
-
-#: ../tui_bootloader.py:225
-msgid "Boot label contains illegal characters."
-msgstr ""
-
-#: ../tui_bootloader.py:255
-msgid "Default"
-msgstr ""
-
-#: ../tui_bootloader.py:273
-#, python-format
-msgid ""
-"The boot manager %s uses can boot other operating systems as well. Please "
-"tell me what partitions you would like to be able to boot and what label you "
-"want to use for each of them."
-msgstr ""
-
-#: ../tui_bootloader.py:286
-msgid ""
-" <Space> select | <F2> select default | <F4> delete | <F12> next screen>"
-msgstr ""
-
-#: ../tui_bootloader.py:335
-msgid "Cannot Delete"
-msgstr ""
-
-#: ../tui_bootloader.py:336
-#, python-format
-msgid ""
-"This boot target cannot be deleted because it is for the %s system you are "
-"about to install."
-msgstr ""
-
-#: ../tui_bootloader.py:378
-msgid ""
-"A boot loader password prevents users from passing arbitrary options to the "
-"kernel. For highest security, you should set a password, but a password is "
-"not necessary for more casual users."
-msgstr ""
-
-#: ../tui_bootloader.py:386
-msgid "Use a GRUB Password"
-msgstr ""
-
-#: ../tui_bootloader.py:399
-msgid "Boot Loader Password:"
-msgstr ""
-
-#: ../tui_bootloader.py:400
-msgid "Confirm:"
-msgstr ""
-
-#: ../tui_bootloader.py:429
-msgid "Passwords Do Not Match"
-msgstr ""
-
-#: ../tui_bootloader.py:430
-msgid "Passwords do not match"
-msgstr ""
-
-#: ../tui_bootloader.py:434
-msgid "Password Too Short"
-msgstr ""
-
-#: ../tui_bootloader.py:435
-msgid "Boot loader password is too short"
-msgstr ""
-
-#: ../tui_bootloader.py:440
-msgid ""
-"Your boot loader password is shorter than six characters. We recommend a "
-"longer boot loader password.\n"
-"\n"
-"Would you like to continue with this password?"
-msgstr ""
-
-#: ../tui_complete.py:25
-msgid ""
-"Press <Enter> to end the installation process.\n"
-"\n"
-msgstr ""
-
-#: ../tui_complete.py:26
-msgid "<Enter> to exit"
-msgstr ""
-
-#: ../tui_complete.py:30
-#, python-format
-msgid ""
-"Congratulations, your %s installation is complete.\n"
-"\n"
-"%s%s"
-msgstr ""
-
-#: ../tui_complete.py:33
-#, python-format
-msgid ""
-"For information on errata (updates and bug fixes), visit %s.\n"
-"\n"
-"Information on using your system is available in the %s wiki at %s."
-msgstr ""
-
-#: ../tui_complete.py:39
-msgid "Complete"
-msgstr ""
-
-#: ../tui_complete.py:40
-msgid "Reboot"
-msgstr ""
-
-#: ../tui_confirm.py:23
-msgid "Installation to begin"
-msgstr ""
-
-#: ../tui_confirm.py:24
-msgid ""
-"Now, we got all information we need for installation. If there is something "
-"you want change you can still go back. If not choose OK to start."
-msgstr ""
-
-#: ../tui_confirm.py:34
-msgid "Reboot?"
-msgstr ""
-
-#: ../tui_confirm.py:35
-msgid "The system will be rebooted now."
-msgstr ""
-
-#: ../tui_keyboard.py:36
-msgid "Keyboard Selection"
-msgstr ""
-
-#: ../tui_keyboard.py:37
-msgid "Which model keyboard is attached to this computer?"
-msgstr ""
-
-#: ../tui_language.py:39
-msgid "Language Selection"
-msgstr ""
-
-#: ../tui_language.py:40
-msgid "What language would you like to use during the installation process?"
-msgstr ""
-
-#: ../tui_network.py:39
-msgid "Hostname"
-msgstr ""
-
-#: ../tui_network.py:42
-msgid ""
-"Please name this computer. The hostname identifies the computer on a "
-"network."
-msgstr ""
-
-#: ../tui_network.py:63 ../tui_network.py:70
-msgid "Invalid Hostname"
-msgstr ""
-
-#: ../tui_network.py:64
-msgid "You have not specified a hostname."
-msgstr ""
-
-#: ../tui_network.py:71
-#, python-format
-msgid ""
-"The hostname \"%s\" is not valid for the following reason:\n"
-"\n"
-"%s"
-msgstr ""
-
-#: ../tui_partition.py:41
-msgid "Must specify a value"
-msgstr ""
-
-#: ../tui_partition.py:44
-msgid "Requested value is not an integer"
-msgstr ""
-
-#: ../tui_partition.py:46
-msgid "Requested value is too large"
-msgstr ""
-
-#: ../tui_partition.py:95 ../tui_partition.py:132
-msgid "Free space"
-msgstr ""
-
-#: ../tui_partition.py:97
-msgid "Extended"
-msgstr ""
-
-#: ../tui_partition.py:111
-msgid "None"
-msgstr ""
-
-#: ../tui_partition.py:178
-#, python-format
-msgid "Could not allocate requested partitions: %s."
-msgstr ""
-
-#: ../tui_partition.py:182
-#, python-format
-msgid "Warning: %s"
-msgstr ""
-
-#: ../tui_partition.py:183
-msgid "Modify Partition"
-msgstr ""
-
-#: ../tui_partition.py:183
-msgid "Add anyway"
-msgstr ""
-
-#: ../tui_partition.py:201 ../tui_partition.py:203 ../tui_partition.py:205
-#: ../tui_partition.py:230
-msgid "<Not Applicable>"
-msgstr ""
-
-#: ../tui_partition.py:220
-msgid "Mount Point:"
-msgstr ""
-
-#: ../tui_partition.py:239
-msgid "File System type:"
-msgstr ""
-
-#: ../tui_partition.py:270
-msgid "Allowable Drives:"
-msgstr ""
-
-#: ../tui_partition.py:292 ../tui_partition.py:371 ../tui_partition.py:419
-msgid "Size (MB):"
-msgstr ""
-
-#: ../tui_partition.py:324
-msgid "Fixed Size:"
-msgstr ""
-
-#: ../tui_partition.py:326
-msgid "Fill maximum size of (MB):"
-msgstr ""
-
-#: ../tui_partition.py:330
-msgid "Fill all available space:"
-msgstr ""
-
-#: ../tui_partition.py:351
-msgid "Start Cylinder:"
-msgstr ""
-
-#: ../tui_partition.py:364
-msgid "End Cylinder:"
-msgstr ""
-
-#: ../tui_partition.py:386
-msgid "Number of spares?"
-msgstr ""
-
-#: ../tui_partition.py:400
-msgid "File System Type:"
-msgstr ""
-
-#: ../tui_partition.py:413
-msgid "File System Label:"
-msgstr ""
-
-#: ../tui_partition.py:424
-msgid "File System Option:"
-msgstr ""
-
-#: ../tui_partition.py:427 ../tui_partition.py:652
-#, python-format
-msgid "Format as %s"
-msgstr ""
-
-#: ../tui_partition.py:429 ../tui_partition.py:654
-#, python-format
-msgid "Migrate to %s"
-msgstr ""
-
-#: ../tui_partition.py:431 ../tui_partition.py:656
-msgid "Leave unchanged"
-msgstr ""
-
-#: ../tui_partition.py:446 ../tui_partition.py:629
-msgid "File System Options"
-msgstr ""
-
-#: ../tui_partition.py:449
-msgid ""
-"Please choose how you would like to prepare the file system on this "
-"partition."
-msgstr ""
-
-#: ../tui_partition.py:457 ../tui_partition.py:607
-msgid "Check for bad blocks"
-msgstr ""
-
-#: ../tui_partition.py:461
-msgid "Leave unchanged (preserve data)"
-msgstr ""
-
-#: ../tui_partition.py:470
-msgid "Format as:"
-msgstr ""
-
-#: ../tui_partition.py:489
-msgid "Migrate to:"
-msgstr ""
-
-#: ../tui_partition.py:559
-msgid "Add Partition"
-msgstr ""
-
-#: ../tui_partition.py:601
-msgid "Force to be a primary partition"
-msgstr ""
-
-#: ../tui_partition.py:684 ../tui_partition.py:738
-msgid "Invalid Entry for Partition Size"
-msgstr ""
-
-#: ../tui_partition.py:696
-msgid "Invalid Entry for Maximum Size"
-msgstr ""
-
-#: ../tui_partition.py:716
-msgid "Invalid Entry for Starting Cylinder"
-msgstr ""
-
-#: ../tui_partition.py:730
-msgid "Invalid Entry for End Cylinder"
-msgstr ""
-
-#: ../tui_partition.py:748 ../tui_partition.py:769
-msgid "Error With Request"
-msgstr ""
-
-#: ../tui_partition.py:838
-msgid "Partitioning"
-msgstr ""
-
-#: ../tui_partition.py:844
-msgid "Start"
-msgstr ""
-
-#: ../tui_partition.py:844
-msgid "End"
-msgstr ""
-
-#: ../tui_partition.py:844
-msgid "Size"
-msgstr ""
-
-#: ../tui_partition.py:844
-msgid "Type"
-msgstr ""
-
-#: ../tui_partition.py:844
-msgid "Mount Point"
-msgstr ""
-
-#: ../tui_partition.py:848
-msgid "New"
-msgstr ""
-
-#: ../tui_partition.py:850
-msgid "Delete"
-msgstr ""
-
-#: ../tui_partition.py:853
-msgid ""
-" F1-Help F2-New F3-Edit F4-Delete F5-Reset F12-OK "
-msgstr ""
-
-#: ../tui_partition.py:883
-msgid "No Root Partition"
-msgstr ""
-
-#: ../tui_partition.py:884
-msgid "Installation requires a / partition."
-msgstr ""
-
-#: ../tui_partition.py:923
-msgid "Partitioning Type"
-msgstr ""
-
-#: ../tui_partition.py:925
-msgid ""
-"Installation requires partitioning of your hard drive. The default layout "
-"is reasonable for most users. You can either choose to use this or create "
-"your own."
-msgstr ""
-
-#: ../tui_partition.py:932
-msgid "Remove all partitions on selected drives and create default layout"
-msgstr ""
-
-#: ../tui_partition.py:933
-msgid "Create custom layout"
-msgstr ""
-
-#: ../tui_partition.py:947
-msgid "Which drive(s) do you want to use for this installation?"
-msgstr ""
-
-#: ../tui_partition.py:960
-msgid "<Space>,<+>,<-> selection | <F2> Add drive | <F12> next screen"
-msgstr ""
-
-#: ../tui_partition.py:1026
-msgid "Review Partition Layout"
-msgstr ""
-
-#: ../tui_partition.py:1027
-msgid "Review and modify partitioning layout?"
-msgstr ""
-
-#: ../tui_progress.py:52
-msgid "File Installation"
-msgstr ""
-
-#: ../tui.py:118
-msgid "Exception Occurred"
-msgstr ""
-
-#: ../tui.py:189
-msgid "Error!"
-msgstr ""
-
-#: ../tui.py:190
-#, python-format
-msgid ""
-"An error occurred when attempting to load an pomona interface component.\n"
-"\n"
-"className = %s\n"
-"\n"
-"Error: %s"
-msgstr ""
-
-#: ../tui.py:195 ../tui.py:197
-msgid "Exit"
-msgstr ""
-
-#: ../tui.py:195 ../tui.py:391
-msgid "Retry"
-msgstr ""
-
-#: ../tui.py:220
-msgid "Cancelled"
-msgstr ""
-
-#: ../tui.py:221
-msgid "I can't go to the previous step from here. You will have to try again."
-msgstr ""
-
-#: ../tui.py:235
-#, python-format
-msgid "Welcome to %s"
-msgstr ""
-
-#: ../tui.py:238
-msgid ""
-" <F1> for help | <Tab> between elements | <Space> selects | <F12> next screen"
-msgstr ""
-
-#: ../tui.py:240
-msgid ""
-" <Tab>/<Alt-Tab> between elements | <Space> selects | <F12> next "
-"screen"
-msgstr ""
-
-#: ../tui.py:285
-msgid "Help not available"
-msgstr ""
-
-#: ../tui.py:286
-msgid "No help is available for this step of the install."
-msgstr ""
-
-#: ../tui.py:387
-msgid "Fix"
-msgstr ""
-
-#: ../tui.py:392
-msgid "Ignore"
-msgstr ""
-
-#: ../tui_timezone.py:63
-msgid "In which time zone are you located?"
-msgstr ""
-
-#: ../tui_timezone.py:78
-msgid "System clock uses UTC"
-msgstr ""
-
-#: ../tui_timezone.py:81
-msgid "Time Zone Selection"
-msgstr ""
-
-#: ../tui_userauth.py:29
-msgid "Root Password"
-msgstr ""
-
-#: ../tui_userauth.py:31
-msgid ""
-"Pick a root password. You must type it twice to ensure you know it and do "
-"not make a typing mistake. Remember that the root password isa critical part "
-"of system security!"
-msgstr ""
-
-#: ../tui_userauth.py:41
-msgid "Password:"
-msgstr ""
-
-#: ../tui_userauth.py:42
-msgid "Password (confirm):"
-msgstr ""
-
-#: ../tui_userauth.py:59
-msgid "Password Length"
-msgstr ""
-
-#: ../tui_userauth.py:60
-msgid "The root password must be at least 6 characters long."
-msgstr ""
-
-#: ../tui_userauth.py:63
-msgid "Password Mismatch"
-msgstr ""
-
-#: ../tui_userauth.py:64
-msgid "The passwords you entered were different. Please try again."
-msgstr ""
-
-#: ../tui_userauth.py:67
-msgid "Error with Password"
-msgstr ""
-
-#: ../tui_userauth.py:68
-msgid ""
-"Requested password contains non-ASCII characters, which are not allowed."
-msgstr ""
-
-#: ../tui_welcome.py:12
-#, python-format
-msgid "%s"
-msgstr ""
-
-#: ../tui_welcome.py:13
-#, python-format
-msgid ""
-"Welcome to %s!\n"
-"\n"
-msgstr ""
-
-#. generated from lang-table
-msgid "English"
-msgstr ""
-
-#. generated from lang-table
-msgid "German"
-msgstr ""
-
-#. generated from lang-table
-msgid "Danish"
-msgstr ""
+++ /dev/null
-#!/bin/sh
-###############################################################################
-# #
-# IPFire.org - A linux based firewall #
-# Copyright (C) 2008 Michael Tremer & Christian Schmidt #
-# #
-# This program is free software: you can redistribute it and/or modify #
-# it under the terms of the GNU General Public License as published by #
-# the Free Software Foundation, either version 3 of the License, or #
-# (at your option) any later version. #
-# #
-# This program is distributed in the hope that it will be useful, #
-# but WITHOUT ANY WARRANTY; without even the implied warranty of #
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
-# GNU General Public License for more details. #
-# #
-# You should have received a copy of the GNU General Public License #
-# along with this program. If not, see <http://www.gnu.org/licenses/>. #
-# #
-###############################################################################
-
-###############################################################################
-# #
-# This is a small wrapper that runs our installer. #
-# #
-###############################################################################
-
-echo "Running the Pomona Installer..."
-
-python /usr/lib/pomona/pomona.py $@
-ret=$?
-
-for i in $@; do
- if [ "$i" == "--debug" ]; then
- echo
- echo "We are running in debug mode!"
- echo
- echo "So, rebooting is paused and you can do some things on the"
- echo "other shells. If you are finished, press ENTER."
- read
- break
- fi
-done
-
-#reboot
-
-cat <<EOF
-
- The installer program has finished with exit code ${ret}.
-
- Please reboot your system or do some debugging work :P
-
-EOF
-sleep 1h
+++ /dev/null
-#!/usr/bin/python
-
-import imputil
-import os
-import sys
-
-from datastore import DataStore
-from dispatch import Dispatcher
-from exception import handleException
-from text import TextInterface
-from log import Logger
-
-from constants import *
-
-import gettext
-_ = lambda x: gettext.ldgettext("pomona", x)
-
-class Installer:
- def __init__(self):
- self.log = Logger()
-
- self.dispatch = None
- self.ds = None
- self.intf = TextInterface(self.log)
- self.window = None
-
- def __call__(self):
- if self.window:
- self.window.pop()
-
- step = self.dispatch.nextStep()
- while step:
- self.log.info("")
- self.log.info("---------- Running step \"%s\" ----------" % step[0])
-
- if type(step[1]) == type(_):
- (name, function) = step
- self.log.debug("\"%s\" is called directly (%s)" % (name, function,))
- rc = function(self)
- if rc in [DISPATCH_BACK, DISPATCH_FORWARD]:
- self.dispatch.dir = rc
- else:
- (file, classes) = step
- substep = 0
- while substep < len(classes):
- while 1:
- try:
- found = imputil.imp.find_module(file)
- loaded = imputil.imp.load_module(classes[substep],
- found[0], found[1],
- found[2])
- nextWindow = loaded.__dict__[classes[substep]]
- break
- except ImportError, e:
- rc = self.intf.messageWindow(_("Error!"),
- _("An error occurred when attempting "
- "to load an pomona interface "
- "component.\n\nclassName = %s\n\n"
- "Error: %s") % (classes[substep],e),
- type="custom", custom_buttons=[_("Exit"), _("Retry")])
- if rc == 0:
- sys.exit(0)
-
- self.window = nextWindow()
- rc = self.window(self)
-
- #if rc == INSTALL_NOOP:
- # rc = lastrc
-
- if rc == INSTALL_BACK:
- #step = step - 1
- self.dispatch.dir = DISPATCH_BACK
- elif rc == INSTALL_OK:
- #step = step + 1
- self.dispatch.dir = DISPATCH_FORWARD
-
- substep += 1
-
- step = self.dispatch.nextStep()
-
-
-
-if __name__ == "__main__":
- # Set up environment
- if not os.environ.has_key("LANG"):
- os.environ["LANG"] = "en_US.UTF-8"
- os.environ['HOME'] = '/tmp'
- os.environ['LC_NUMERIC'] = 'C'
-
- installer = Installer()
-
- sys.excepthook = lambda type, value, tb, installer=installer: \
- handleException(installer, (type, value, tb))
-
- # Display some information
- installer.window = \
- installer.intf.waitWindow(_("Installer"), _("Setting up installer..."),)
- installer.log.info("Going on to install %s-v%s (%s)..." % \
- (PRODUCT_NAME, PRODUCT_VERSION, PRODUCT_SLOGAN,))
-
- # Applying classes to installer
- installer.dispatch = Dispatcher(installer)
- installer.ds = DataStore(installer)
-
- try:
- installer()
- except SystemExit, code:
- pass
- except:
- handleException(installer, sys.exc_info())
-
- del installer.intf
- del installer
+++ /dev/null
-deleted
-filter
-setattr
-^$
-^Warnings...$
-^pomona.py:[0-9]*: Catching a non-Exception object \(SystemExit\)$
-Note this last line must never end with a newline
\ No newline at end of file
+++ /dev/null
-#!/bin/bash
-
-# This script will check pomona for any pychecker warning using a set of
-# options minimizing false positives, in combination with filtering of any
-# warning regularexpressions listed in pychecker-false-positives.
-#
-# If any warnings our found they will be stored in pychecker-log and printed
-# to stdout and this script will exit with a status of 1, if no (non filtered)
-# warnings are found it exits with a status of 0
-
-FALSE_POSITIVES=pychecker-false-positives
-NON_STRICT_OPTIONS="--no-deprecated --no-returnvalues --no-abstract"
-
-usage () {
- echo "usage: `basename $0` [--strict] [--help]"
- exit $1
-}
-
-while [ $# -gt 0 ]; do
- case $1 in
- --strict)
- NON_STRICT_OPTIONS=""
- ;;
- --help)
- usage 0
- ;;
- *)
- echo "Error unknown option: $1"
- usage 1
- esac
- shift
-done
-
-if [ "`tail -c 1 pychecker-false-positives`" == "`echo`" ]; then
- echo "Error $FALSE_POSITIVES ends with an enter."
- echo "Error the last line of $FALSE_POSITIVES should never have an enter!"
- exit 1
-fi
-
-export PYTHONPATH="isys"
-
-#for file in *.py isys/*.py; do FILES="${FILES} ${file}"; done
-FILES=$(find . -name "*.py")
-
-pychecker --only --limit 1000 \
- --maxlines 500 --maxargs 20 --maxbranches 80 --maxlocals 60 --maxreturns 20 \
- --no-callinit --no-local --no-shadow --no-shadowbuiltin \
- --no-import --no-miximport --no-pkgimport --no-reimport \
- --no-argsused --no-varargsused --no-override \
- $NON_STRICT_OPTIONS $FILES | \
- egrep -v "`cat $FALSE_POSITIVES | tr '\n' '|'`" > pychecker-log
-
-if [ -s pychecker-log ]; then
- echo "Pychecker reports the following issues:"
- cat pychecker-log
- exit 1
-fi
-
-rm pychecker-log
-
-exit 0
+++ /dev/null
-#!/usr/bin/python
-
-from devicetree import DeviceTree
-
-from deviceaction import *
-from devicelibs import lvm
-from devicelibs.lvm import safeLvmName
-from devices import *
-from formats import get_default_filesystem_type
-from udev import *
-
-from constants import *
-
-import gettext
-_ = lambda x: gettext.ldgettext("pomona", x)
-
-def storageInitialize(installer):
- storage = installer.ds.storage
-
- storage.shutdown()
-
- if installer.dispatch.dir == DISPATCH_BACK:
- return
-
- # XXX I don't understand why I have to do this
- udev_trigger(subsystem="block")
-
- #XXX Determine our cdrom drive/usb key here and add it to protectedPartiotions
- storage.reset()
-
-class Storage(object):
- def __init__(self, installer):
- self.installer = installer
-
- self.protectedDisks = []
- self.clearDisks = []
- self.ignoredDisks = []
-
- self.defaultFSType = get_default_filesystem_type()
- self.defaultBootFSType = get_default_filesystem_type(boot=True)
-
- self.doAutoPartition = False
- self.encryptedAutoPart = False
- #self.autoPartitionRequests = []
- self.autoPartitionRequests = [PartSpec(mountpoint="/", fstype=self.defaultFSType, size=1024, grow=True),
- PartSpec(mountpoint="/boot", fstype=self.defaultFSType, size=75, grow=False),]
-
- #self.devicetree = DeviceTree(self.installer)
- self.devicetree = None
-
- self._nextID = 0
-
- def shutdown(self):
- self.installer.log.debug("Shutting down storage...")
-
- def reset(self):
- """ Reset storage configuration to reflect actual system state.
-
- This should rescan from scratch but not clobber user-obtained
- information like passphrases
- """
- #for device in self.devices:
- # if device.format.type == "luks" and device.format.exists:
- # self.__luksDevs[device.format.uuid] = device.format._LUKS__passphrase
-
- self.installer.window = self.installer.intf.waitWindow(_("Finding Devices"),
- _("Finding storage devices..."))
- self.devicetree = DeviceTree(self.installer)
- self.devicetree.populate()
- self.fsset = FSSet(self.installer)
- self.installer.window.pop()
-
- def checkNoDisks(self):
- """Check that there are valid disk devices."""
- if not self.disks:
- self.installer.intf.messageWindow(_("No Drives Found"),
- _("An error has occurred - no valid devices were "
- "found on which to create new file systems. "
- "Please check your hardware for the cause "
- "of this problem."))
- return True
- return False
-
- def sanityCheck(self):
- """ Run a series of tests to verify the storage configuration.
-
- This function is called at the end of partitioning so that
- we can make sure you don't have anything silly (like no /,
- a really small /, etc). Returns (errors, warnings) where
- each is a list of strings.
- """
- checkSizes = [('/usr', 250), ('/tmp', 50), ('/var', 384),
- ('/home', 100), ('/boot', 75)]
- warnings = []
- errors = []
-
- filesystems = self.fsset.mountpoints
- root = self.fsset.rootDevice
- swaps = self.fsset.swapDevices
- #try:
- # boot = self.anaconda.platform.bootDevice()
- #except DeviceError:
- # boot = None
- boot = None
-
- if not root:
- errors.append(_("You have not defined a root partition (/), "
- "which is required for installation of %s "
- "to continue.") % (PRODUCT_NAME,))
-
- if root and root.size < 250:
- warnings.append(_("Your root partition is less than 250 "
- "megabytes which is usually too small to "
- "install %s.") % (PRODUCT_NAME,))
-
- recommended_size = 1024
- if (root and root.size < recommended_size):
- errors.append(_("Your / partition is less than %s "
- "megabytes which is lower than recommended "
- "for a normal %s install.")
- %(recommended_size, PRODUCT_NAME))
-
- # livecds have to have the rootfs type match up
- #if (root and
- # self.installer.backend.rootFsType and
- # root.format.type != self.installer.backend.rootFsType):
- # errors.append(_("Your / partition does not match the "
- # "the live image you are installing from. "
- # "It must be formatted as %s.")
- # % (self.anaconda.backend.rootFsType,))
-
- for (mount, size) in checkSizes:
- if mount in filesystems and filesystems[mount].size < size:
- warnings.append(_("Your %s partition is less than %s "
- "megabytes which is lower than recommended "
- "for a normal %s install.")
- %(mount, size, PRODUCT_NAME))
-
- usb_disks = []
- firewire_disks = []
- #for disk in self.disks:
- # if isys.driveUsesModule(disk.name, ["usb-storage", "ub"]):
- # usb_disks.append(disk)
- # elif isys.driveUsesModule(disk.name, ["sbp2", "firewire-sbp2"]):
- # firewire_disks.append(disk)
-
- uses_usb = False
- uses_firewire = False
- for device in filesystems.values():
- for disk in usb_disks:
- if device.dependsOn(disk):
- uses_usb = True
- break
-
- for disk in firewire_disks:
- if device.dependsOn(disk):
- uses_firewire = True
- break
-
- if uses_usb:
- warnings.append(_("Installing on a USB device. This may "
- "or may not produce a working system."))
- if uses_firewire:
- warnings.append(_("Installing on a FireWire device. This may "
- "or may not produce a working system."))
-
- if not boot:
- errors.append(_("You have not created a boot partition."))
-
- if (boot and boot.type == "mdarray" and
- boot.level != 1):
- errors.append(_("Bootable partitions can only be on RAID1 "
- "devices."))
-
- # can't have bootable partition on LV
- if boot and boot.type == "lvmlv":
- errors.append(_("Bootable partitions cannot be on a "
- "logical volume."))
-
- # most arches can't have boot on RAID
- if boot and boot.type == "mdarray" and not self.anaconda.platform.supportsMdRaidBoot:
- errors.append(_("Bootable partitions cannot be on a RAID "
- "device."))
-
- # Lots of filesystems types don't support /boot.
- if boot and not boot.format.bootable:
- errors.append(_("Bootable partitions cannot be on an %s "
- "filesystem.") % boot.format.name)
-
- # vfat /boot is insane.
- if (boot and boot == root and boot.format.type == "vfat"):
- errors.append(_("Bootable partitions cannot be on an %s "
- "filesystem.") % boot.format.type)
-
- if (boot and filter(lambda d: d.type == "luks/dm-crypt",
- self.deviceDeps(boot))):
- errors.append(_("Bootable partitions cannot be on an "
- "encrypted block device"))
-
- if not swaps:
- warnings.append(_("You have not specified a swap partition. "
- "Although not strictly required in all cases, "
- "it will significantly improve performance for "
- "most installations."))
-
- return (errors, warnings)
-
- def deviceDeps(self, device):
- return self.devicetree.getDependentDevices(device)
-
- @property
- def nextID(self):
- id = self._nextID
- self._nextID += 1
- return id
-
- @property
- def disks(self):
- """ A list of the disks in the device tree.
-
- Ignored disks are not included, as are disks with no media present.
-
- This is based on the current state of the device tree and
- does not necessarily reflect the actual on-disk state of the
- system's disks.
- """
- disks = []
- devices = self.devicetree.devices
- for d in devices:
- if isinstance(devices[d], DiskDevice) and devices[d].mediaPresent:
- disks.append(devices[d])
- disks.sort(key=lambda d: d.name)
- return disks
-
- @property
- def devices(self):
- """ A list of all the devices in the device tree. """
- devices = self.devicetree.devices.values()
- devices.sort(key=lambda d: d.path)
- return devices
-
- @property
- def partitions(self):
- """ A list of the partitions in the device tree.
-
- This is based on the current state of the device tree and
- does not necessarily reflect the actual on-disk state of the
- system's disks.
- """
- partitions = self.devicetree.getDevicesByInstance(PartitionDevice)
- partitions.sort(key=lambda d: d.name)
- return partitions
-
- @property
- def vgs(self):
- """ A list of the LVM Volume Groups in the device tree.
-
- This is based on the current state of the device tree and
- does not necessarily reflect the actual on-disk state of the
- system's disks.
- """
- vgs = self.devicetree.getDevicesByType("lvmvg")
- vgs.sort(key=lambda d: d.name)
- return vgs
-
- def createDevice(self, device):
- """ Schedule creation of a device.
-
- TODO: We could do some things here like assign the next
- available raid minor if one isn't already set.
- """
- self.devicetree.registerAction(ActionCreateDevice(self.installer, device))
- if device.format.type:
- self.devicetree.registerAction(ActionCreateFormat(self.installer, device))
-
- def destroyDevice(self, device):
- """ Schedule destruction of a device. """
- if device.format.exists and device.format.type:
- # schedule destruction of any formatting while we're at it
- self.devicetree.registerAction(ActionDestroyFormat(self.installer, device))
-
- action = ActionDestroyDevice(self.installer, device)
- self.devicetree.registerAction(action)
-
- def newPartition(self, *args, **kwargs):
- """ Return a new PartitionDevice instance for configuring. """
- if kwargs.has_key("fmt_type"):
- kwargs["format"] = getFormat(kwargs.pop("fmt_type"), installer=self.installer,
- mountpoint=kwargs.pop("mountpoint", None))
-
- if kwargs.has_key("disks"):
- parents = kwargs.pop("disks")
- if isinstance(parents, Device):
- kwargs["parents"] = [parents]
- else:
- kwargs["parents"] = parents
-
- if kwargs.has_key("name"):
- name = kwargs.pop("name")
- else:
- name = "req%d" % self.nextID
-
- return PartitionDevice(self.installer, name, *args, **kwargs)
-
- def newVG(self, *args, **kwargs):
- """ Return a new LVMVolumeGroupDevice instance. """
- pvs = kwargs.pop("pvs", [])
- for pv in pvs:
- if pv not in self.devices:
- raise ValueError("pv is not in the device tree")
-
- if kwargs.has_key("name"):
- name = kwargs.pop("name")
- else:
- # XXX name = self.createSuggestedVGName(self.anaconda.id.network)
- name = self.createSuggestedVGName(None)
-
- if name in [d.name for d in self.devices]:
- raise ValueError("name already in use")
-
- return LVMVolumeGroupDevice(self.installer, name, pvs, *args, **kwargs)
-
- def newLV(self, *args, **kwargs):
- """ Return a new LVMLogicalVolumeDevice instance. """
- if kwargs.has_key("vg"):
- vg = kwargs.pop("vg")
-
- mountpoint = kwargs.pop("mountpoint", None)
- if kwargs.has_key("fmt_type"):
- kwargs["format"] = getFormat(kwargs.pop("fmt_type"),
- installer=self.installer,
- mountpoint=mountpoint)
-
- if kwargs.has_key("name"):
- name = kwargs.pop("name")
- else:
- if kwargs.get("format") and kwargs["format"].type == "swap":
- swap = True
- else:
- swap = False
- name = self.createSuggestedLVName(vg,
- swap=swap,
- mountpoint=mountpoint)
-
- if name in [d.name for d in self.devices]:
- raise ValueError("Name already in use")
-
- return LVMLogicalVolumeDevice(self.installer, name, vg, *args, **kwargs)
-
- def createSuggestedVGName(self, network):
- """ Return a reasonable, unused VG name. """
- # try to create a volume group name incorporating the hostname
- #hn = network.hostname # XXX
- hn = "%s.localdomain" % PROCUCT_SNAME
- vgnames = [vg.name for vg in self.vgs]
- if hn is not None and hn != '':
- if hn == 'localhost' or hn == 'localhost.localdomain':
- vgtemplate = "VolGroup"
- elif hn.find('.') != -1:
- hn = safeLvmName(hn)
- vgtemplate = "vg_%s" % (hn.split('.')[0].lower(),)
- else:
- hn = safeLvmName(hn)
- vgtemplate = "vg_%s" % (hn.lower(),)
- else:
- vgtemplate = "VolGroup"
-
- if vgtemplate not in vgnames and \
- vgtemplate not in lvm.lvm_vg_blacklist:
- return vgtemplate
- else:
- i = 0
- while 1:
- tmpname = "%s%02d" % (vgtemplate, i,)
- if not tmpname in vgnames and \
- tmpname not in lvm.lvm_vg_blacklist:
- break
-
- i += 1
- if i > 99:
- tmpname = ""
-
- return tmpname
-
- def createSuggestedLVName(self, vg, swap=None, mountpoint=None):
- """ Return a suitable, unused name for a new logical volume. """
- # FIXME: this is not at all guaranteed to work
- if mountpoint:
- # try to incorporate the mountpoint into the name
- if mountpoint == '/':
- lvtemplate = 'lv_root'
- else:
- tmp = safeLvmName(mountpoint)
- lvtemplate = "lv_%s" % (tmp,)
- else:
- if swap:
- if len([s for s in self.swaps if s in vg.lvs]):
- idx = len([s for s in self.swaps if s in vg.lvs])
- while True:
- lvtemplate = "lv_swap%02d" % idx
- if lvtemplate in [lv.lvname for lv in vg.lvs]:
- idx += 1
- else:
- break
- else:
- lvtemplate = "lv_swap"
- else:
- idx = len(vg.lvs)
- while True:
- lvtemplate = "LogVol%02d" % idx
- if lvtemplate in [l.lvname for l in vg.lvs]:
- idx += 1
- else:
- break
-
- return lvtemplate
-
- def deviceImmutable(self, device):
- """ Return any reason the device cannot be modified/removed.
-
- Return False if the device can be removed.
-
- Devices that cannot be removed include:
-
- - protected partitions
- - devices that are part of an md array or lvm vg
- - extended partition containing logical partitions that
- meet any of the above criteria
-
- """
- if not isinstance(device, Device):
- raise ValueError("arg1 (%s) must be a Device instance" % device)
-
- if device.name in self.protectedDisks:
- return _("This partition is holding the data for the hard "
- "drive install.")
- elif device.format.type == "mdmember":
- for array in self.mdarrays:
- if array.dependsOn(device):
- if array.minor is not None:
- return _("This device is part of the RAID "
- "device %s.") % (array.path,)
- else:
- return _("This device is part of a RAID device.")
- elif device.format.type == "lvmpv":
- for vg in self.vgs:
- if vg.dependsOn(device):
- if vg.name is not None:
- return _("This device is part of the LVM "
- "volume group '%s'.") % (vg.name,)
- else:
- return _("This device is part of a LVM volume "
- "group.")
- elif device.format.type == "luks":
- try:
- luksdev = self.devicetree.getChildren(device)[0]
- except IndexError:
- pass
- else:
- return self.deviceImmutable(luksdev)
- elif isinstance(device, PartitionDevice) and device.isExtended:
- reasons = {}
- for dep in self.deviceDeps(device):
- reason = self.deviceImmutable(dep)
- if reason:
- reasons[dep.path] = reason
- if reasons:
- msg = _("This device is an extended partition which "
- "contains logical partitions that cannot be "
- "deleted:\n\n")
- for dev in reasons:
- msg += "%s: %s" % (dev, reasons[dev])
- return msg
-
- for i in self.devicetree.immutableDevices:
- if i[0] == device.name:
- return i[1]
-
- return False
-
-
-class FSSet(object):
- """ A class to represent a set of filesystems. """
- def __init__(self, installer):
- self.installer = installer
- self.devicetree = installer.ds.storage.devicetree
- self.cryptTab = None
- self.blkidTab = None
- self.origFStab = None
- self.active = False
- self._dev = None
- self._devpts = None
- self._sysfs = None
- self._proc = None
- self._devshm = None
-
- @property
- def sysfs(self):
- if not self._sysfs:
- self._sysfs = NoDevice(format=getFormat("sysfs",
- device="sys",
- mountpoint="/sys"))
- return self._sysfs
-
- @property
- def dev(self):
- if not self._dev:
- self._dev = DirectoryDevice("/dev", format=getFormat("bind",
- device="/dev",
- mountpoint="/dev",
- exists=True),
- exists=True)
-
- return self._dev
-
- @property
- def devpts(self):
- if not self._devpts:
- self._devpts = NoDevice(format=getFormat("devpts",
- device="devpts",
- mountpoint="/dev/pts"))
- return self._devpts
-
- @property
- def proc(self):
- if not self._proc:
- self._proc = NoDevice(format=getFormat("proc",
- device="proc",
- mountpoint="/proc"))
- return self._proc
-
- @property
- def devshm(self):
- if not self._devshm:
- self._devshm = NoDevice(format=getFormat("tmpfs",
- device="tmpfs",
- mountpoint="/dev/shm"))
- return self._devshm
-
- @property
- def devices(self):
- devices = self.devicetree.devices.values()
- devices.sort(key=lambda d: d.path)
- return devices
-
- @property
- def mountpoints(self):
- filesystems = {}
- for device in self.devices:
- if device.format.mountable and device.format.mountpoint:
- filesystems[device.format.mountpoint] = device
- return filesystems
-
- def _parseOneLine(self, (devspec, mountpoint, fstype, options, dump, passno)):
- # find device in the tree
- device = self.devicetree.resolveDevice(devspec,
- cryptTab=self.cryptTab,
- blkidTab=self.blkidTab)
- if device:
- # fall through to the bottom of this block
- pass
- elif devspec.startswith("/dev/loop"):
- # FIXME: create devices.LoopDevice
- self.installer.log.warning("completely ignoring your loop mount")
- elif ":" in devspec:
- # NFS -- preserve but otherwise ignore
- device = NFSDevice(devspec,
- format=getFormat(fstype,
- device=devspec))
- elif devspec.startswith("/") and fstype == "swap":
- # swap file
- device = FileDevice(devspec,
- parents=get_containing_device(devspec, self.devicetree),
- format=getFormat(fstype,
- device=devspec,
- exists=True),
- exists=True)
- elif fstype == "bind" or "bind" in options:
- # bind mount... set fstype so later comparison won't
- # turn up false positives
- fstype = "bind"
- device = FileDevice(devspec,
- parents=get_containing_device(devspec, self.devicetree),
- exists=True)
- device.format = getFormat("bind",
- device=device.path,
- exists=True)
- elif mountpoint in ("/proc", "/sys", "/dev/shm", "/dev/pts"):
- # drop these now -- we'll recreate later
- return None
- else:
- # nodev filesystem -- preserve or drop completely?
- format = getFormat(fstype)
- if devspec == "none" or \
- isinstance(format, get_device_format_class("nodev")):
- device = NoDevice(format)
- else:
- device = StorageDevice(devspec)
-
- if device is None:
- self.installer.log.error("failed to resolve %s (%s) from fstab" % (devspec,
- fstype))
- return None
-
- # make sure, if we're using a device from the tree, that
- # the device's format we found matches what's in the fstab
- fmt = getFormat(fstype, device=device.path)
- if fmt.type != device.format.type:
- self.installer.log.warning("scanned format (%s) differs from fstab "
- "format (%s)" % (device.format.type, fstype))
-
- if device.format.mountable:
- device.format.mountpoint = mountpoint
- device.format.mountopts = options
-
- # is this useful?
- try:
- device.format.options = options
- except AttributeError:
- pass
-
- return device
-
- def parseFSTab(self, chroot=""):
- """ parse /etc/fstab
-
- preconditions:
- all storage devices have been scanned, including filesystems
- postconditions:
-
- FIXME: control which exceptions we raise
-
- XXX do we care about bind mounts?
- how about nodev mounts?
- loop mounts?
- """
- if not chroot or not os.path.isdir(chroot):
- chroot = ""
-
- path = "%s/etc/fstab" % chroot
- if not os.access(path, os.R_OK):
- # XXX should we raise an exception instead?
- self.installer.log.info("cannot open %s for read" % path)
- return
-
- blkidTab = BlkidTab(self.installer, chroot=chroot)
- try:
- blkidTab.parse()
- self.installer.log.debug("blkid.tab devs: %s" % blkidTab.devices.keys())
- except Exception as e:
- self.installer.log.info("error parsing blkid.tab: %s" % e)
- blkidTab = None
-
- cryptTab = CryptTab(self.devicetree, blkidTab=blkidTab, chroot=chroot)
- try:
- cryptTab.parse(chroot=chroot)
- self.installer.log.debug("crypttab maps: %s" % cryptTab.mappings.keys())
- except Exception as e:
- self.installer.log.info("error parsing crypttab: %s" % e)
- cryptTab = None
-
- self.blkidTab = blkidTab
- self.cryptTab = cryptTab
-
- with open(path) as f:
- self.installer.log.debug("parsing %s" % path)
-
- lines = f.readlines()
-
- # save the original file
- self.origFStab = ''.join(lines)
-
- for line in lines:
- # strip off comments
- (line, pound, comment) = line.partition("#")
- fields = line.split()
-
- if not 4 <= len(fields) <= 6:
- continue
- elif len(fields) == 4:
- fields.extend([0, 0])
- elif len(fields) == 5:
- fields.append(0)
-
- (devspec, mountpoint, fstype, options, dump, passno) = fields
-
- try:
- device = self._parseOneLine((devspec, mountpoint, fstype, options, dump, passno))
- except Exception as e:
- raise Exception("fstab entry %s is malformed: %s" % (devspec, e))
-
- if not device:
- continue
-
- if device not in self.devicetree.devices.values():
- self.devicetree._addDevice(device)
-
- def fsFreeSpace(self, chroot='/'):
- space = []
- for device in self.devices:
- if not device.format.mountable or \
- not device.format.status:
- continue
-
- path = "%s/%s" % (chroot, device.format.mountpoint)
- try:
- space.append((device.format.mountpoint,
- isys.pathSpaceAvailable(path)))
- except SystemError:
- self.installer.log.error("failed to calculate free space for %s" % (device.format.mountpoint,))
-
- space.sort(key=lambda s: s[1])
- return space
-
- def mtab(self):
- format = "%s %s %s %s 0 0\n"
- mtab = ""
- devices = self.mountpoints.values() + self.swapDevices
- devices.extend([self.devshm, self.devpts, self.sysfs, self.proc])
- devices.sort(key=lambda d: getattr(d.format, "mountpoint", None))
- for device in devices:
- if not device.format.status:
- continue
- if not device.format.mountable:
- continue
- if device.format.mountpoint:
- options = device.format.mountopts
- if options:
- options = options.replace("defaults,", "")
- options = options.replace("defaults", "")
-
- if options:
- options = "rw," + options
- else:
- options = "rw"
- mtab = mtab + format % (device.path,
- device.format.mountpoint,
- device.format.type,
- options)
- return mtab
-
- def turnOnSwap(self):
- intf = self.installer.intf
- for device in self.swapDevices:
- try:
- device.setup()
- device.format.setup()
- except SuspendError:
- if intf:
- msg = _("The swap device:\n\n %s\n\n"
- "in your /etc/fstab file is currently in "
- "use as a software suspend device, "
- "which means your system is hibernating. "
- "If you are performing a new install, "
- "make sure the installer is set "
- "to format all swap devices.") \
- % device.path
- intf.messageWindow(_("Error"), msg)
- sys.exit(0)
- except DeviceError as msg:
- if intf:
- err = _("Error enabling swap device %s: %s\n\n"
- "This most likely means this swap "
- "device has not been initialized.\n\n"
- "Press OK to exit the installer.") % \
- (device.path, msg)
- intf.messageWindow(_("Error"), err)
- sys.exit(0)
-
- def mountFilesystems(self, installer, raiseErrors=None, readOnly=None,
- skipRoot=False):
- intf = installer.intf
- devices = self.mountpoints.values() + self.swapDevices
- devices.extend([self.dev, self.devshm, self.devpts, self.sysfs, self.proc])
- devices.sort(key=lambda d: getattr(d.format, "mountpoint", None))
-
- for device in devices:
- if not device.format.mountable or not device.format.mountpoint:
- continue
-
- if skipRoot and device.format.mountpoint == "/":
- continue
-
- options = device.format.options
- if "noauto" in options.split(","):
- continue
-
- try:
- device.setup()
- except Exception as msg:
- # FIXME: need an error popup
- continue
-
- if readOnly:
- options = "%s,%s" % (options, readOnly)
-
- try:
- device.format.setup(options=options,
- chroot=installer.rootPath)
- except OSError as (num, msg):
- if intf:
- if num == errno.EEXIST:
- intf.messageWindow(_("Invalid mount point"),
- _("An error occurred when trying "
- "to create %s. Some element of "
- "this path is not a directory. "
- "This is a fatal error and the "
- "install cannot continue.\n\n"
- "Press <Enter> to exit the "
- "installer.")
- % (device.format.mountpoint,))
- else:
- intf.messageWindow(_("Invalid mount point"),
- _("An error occurred when trying "
- "to create %s: %s. This is "
- "a fatal error and the install "
- "cannot continue.\n\n"
- "Press <Enter> to exit the "
- "installer.")
- % (device.format.mountpoint, msg))
- self.installer.log.error("OSError: (%d) %s" % (num, msg) )
- sys.exit(0)
- except SystemError as (num, msg):
- if raiseErrors:
- raise
- if intf and not device.format.linuxNative:
- ret = intf.messageWindow(_("Unable to mount filesystem"),
- _("An error occurred mounting "
- "device %s as %s. You may "
- "continue installation, but "
- "there may be problems.") %
- (device.path,
- device.format.mountpoint),
- type="custom",
- custom_icon="warning",
- custom_buttons=[_("_Exit installer"),
- _("_Continue")])
-
- if ret == 0:
- sys.exit(0)
- else:
- continue
-
- self.installer.log.error("SystemError: (%d) %s" % (num, msg) )
- sys.exit(0)
- except FSError as msg:
- if intf:
- intf.messageWindow(_("Unable to mount filesystem"),
- _("An error occurred mounting "
- "device %s as %s: %s. This is "
- "a fatal error and the install "
- "cannot continue.\n\n"
- "Press <Enter> to exit the "
- "installer.")
- % (device.path,
- device.format.mountpoint,
- msg))
- self.installer.log.error("FSError: %s" % msg)
- sys.exit(0)
-
- self.active = True
-
- def umountFilesystems(self, instPath, ignoreErrors=True, swapoff=True):
- devices = self.mountpoints.values() + self.swapDevices
- devices.extend([self.dev, self.devshm, self.devpts, self.sysfs, self.proc])
- devices.sort(key=lambda d: getattr(d.format, "mountpoint", None))
- devices.reverse()
- for device in devices:
- if not device.format.mountable and \
- (device.format.type != "swap" or swapoff):
- continue
-
- device.format.teardown()
- device.teardown()
-
- self.active = False
-
- def createSwapFile(self, rootPath, device, size):
- """ Create and activate a swap file under rootPath. """
- filename = "/SWAP"
- count = 0
- basedir = os.path.normpath("%s/%s" % (rootPath,
- device.format.mountpoint))
- while os.path.exists("%s/%s" % (basedir, filename)) or \
- self.devicetree.getDeviceByName(filename):
- file = os.path.normpath("%s/%s" % (basedir, filename))
- count += 1
- filename = "/SWAP-%d" % count
-
- dev = FileDevice(filename,
- size=size,
- parents=[device],
- format=getFormat("swap", device=filename))
- dev.create()
- dev.setup()
- dev.format.create()
- dev.format.setup()
- # nasty, nasty
- self.devicetree._addDevice(dev)
-
- def mkDevRoot(self, instPath):
- root = self.rootDevice
- dev = "%s/%s" % (instPath, root.path)
- if not os.path.exists("%s/dev/root" %(instPath,)) and os.path.exists(dev):
- rdev = os.stat(dev).st_rdev
- os.mknod("%s/dev/root" % (instPath,), stat.S_IFBLK | 0600, rdev)
-
- @property
- def swapDevices(self):
- swaps = []
- for device in self.devices:
- if device.format.type == "swap":
- swaps.append(device)
- return swaps
-
- @property
- def rootDevice(self):
- for device in self.devices:
- try:
- mountpoint = device.format.mountpoint
- except AttributeError:
- mountpoint = None
-
- if mountpoint == "/":
- return device
-
- @property
- def migratableDevices(self):
- """ List of devices whose filesystems can be migrated. """
- migratable = []
- for device in self.devices:
- if device.format.migratable and device.format.exists:
- migratable.append(device)
-
- return migratable
-
- def write(self, instPath):
- """ write out all config files based on the set of filesystems """
- # /etc/fstab
- fstab_path = os.path.normpath("%s/etc/fstab" % instPath)
- fstab = self.fstab()
- open(fstab_path, "w").write(fstab)
-
- # /etc/crypttab
- crypttab_path = os.path.normpath("%s/etc/crypttab" % instPath)
- crypttab = self.crypttab()
- open(crypttab_path, "w").write(crypttab)
-
- # /etc/mdadm.conf
- mdadm_path = os.path.normpath("%s/etc/mdadm.conf" % instPath)
- mdadm_conf = self.mdadmConf()
- open(mdadm_path, "w").write(mdadm_conf)
-
- def crypttab(self):
- # if we are upgrading, do we want to update crypttab?
- # gut reaction says no, but plymouth needs the names to be very
- # specific for passphrase prompting
- if not self.cryptTab:
- self.cryptTab = CryptTab(self.devicetree)
- self.cryptTab.populate()
-
- devices = self.mountpoints.values() + self.swapDevices
-
- # prune crypttab -- only mappings required by one or more entries
- for name in self.cryptTab.mappings.keys():
- keep = False
- mapInfo = self.cryptTab[name]
- cryptoDev = mapInfo['device']
- for device in devices:
- if device == cryptoDev or device.dependsOn(cryptoDev):
- keep = True
- break
-
- if not keep:
- del self.cryptTab.mappings[name]
-
- return self.cryptTab.crypttab()
-
- def mdadmConf(self):
- """ Return the contents of mdadm.conf. """
- arrays = self.devicetree.getDevicesByType("mdarray")
- conf = ""
- devices = self.mountpoints.values() + self.swapDevices
- for array in arrays:
- writeConf = False
- for device in devices:
- if device == array or device.dependsOn(array):
- writeConf = True
- break
-
- if writeConf:
- conf += array.mdadmConfEntry
-
- return conf
-
- def fstab (self):
- format = "%-23s %-23s %-7s %-15s %d %d\n"
- fstab = """
-#
-# /etc/fstab
-# Created by pomona on %s
-#
-# Accessible filesystems, by reference, are maintained under '/dev/disk'
-# See man pages fstab(5), findfs(8), mount(8) and/or vol_id(8) for more info
-#
-""" % time.asctime()
-
- devices = self.mountpoints.values() + self.swapDevices
- devices.extend([self.devshm, self.devpts, self.sysfs, self.proc])
- netdevs = self.devicetree.getDevicesByInstance(NetworkStorageDevice)
- for device in devices:
- # why the hell do we put swap in the fstab, anyway?
- if not device.format.mountable and device.format.type != "swap":
- continue
-
- fstype = device.format.type
- if fstype == "swap":
- mountpoint = "swap"
- options = device.format.options
- else:
- mountpoint = device.format.mountpoint
- options = device.format.mountopts
- if not mountpoint:
- self.installer.log.warning("%s filesystem on %s has no mountpoint" % \
- (fstype, device.path))
- continue
-
- options = options or "defaults"
- for netdev in netdevs:
- if device.dependsOn(netdev):
- options = options + ",_netdev"
- break
- devspec = device.fstabSpec
- dump = device.format.dump
- if device.format.check and mountpoint == "/":
- passno = 1
- elif device.format.check:
- passno = 2
- else:
- passno = 0
- fstab = fstab + device.fstabComment
- fstab = fstab + format % (devspec, mountpoint, fstype,
- options, dump, passno)
- return fstab
-
-class PartSpec(object):
- def __init__(self, mountpoint=None, fstype=None, size=None, maxSize=None,
- grow=False, asVol=False, weight=0):
- self.mountpoint = mountpoint
- self.fstype = fstype
- self.size = size
- self.maxSize = maxSize
- self.grow = grow
- self.asVol = asVol
- self.weight = weight
-
-
-class BlkidTab(object):
- """ Dictionary-like interface to blkid.tab with device path keys """
- def __init__(self, installer, chroot=""):
- self.installer = installer
- self.chroot = chroot
- self.devices = {}
-
- def parse(self):
- path = "%s/etc/blkid/blkid.tab" % self.chroot
- self.installer.log.debug("parsing %s" % path)
- with open(path) as f:
- for line in f.readlines():
- # this is pretty ugly, but an XML parser is more work than
- # is justifiable for this purpose
- if not line.startswith("<device "):
- continue
-
- line = line[len("<device "):-len("</device>\n")]
- (data, sep, device) = line.partition(">")
- if not device:
- continue
-
- self.devices[device] = {}
- for pair in data.split():
- try:
- (key, value) = pair.split("=")
- except ValueError:
- continue
-
- self.devices[device][key] = value[1:-1] # strip off quotes
-
- def __getitem__(self, key):
- return self.devices[key]
-
- def get(self, key, default=None):
- return self.devices.get(key, default)
-
-
-class CryptTab(object):
- """ Dictionary-like interface to crypttab entries with map name keys """
- def __init__(self, devicetree, blkidTab=None, chroot=""):
- self.devicetree = devicetree
- self.blkidTab = blkidTab
- self.chroot = chroot
- self.mappings = {}
-
- def parse(self, chroot=""):
- """ Parse /etc/crypttab from an existing installation. """
- if not chroot or not os.path.isdir(chroot):
- chroot = ""
-
- path = "%s/etc/crypttab" % chroot
- log.debug("parsing %s" % path)
- with open(path) as f:
- if not self.blkidTab:
- try:
- self.blkidTab = BlkidTab(chroot=chroot)
- self.blkidTab.parse()
- except Exception:
- self.blkidTab = None
-
- for line in f.readlines():
- (line, pound, comment) = line.partition("#")
- fields = line.split()
- if not 2 <= len(fields) <= 4:
- continue
- elif len(fields) == 2:
- fields.extend(['none', ''])
- elif len(fields) == 3:
- fields.append('')
-
- (name, devspec, keyfile, options) = fields
-
- # resolve devspec to a device in the tree
- device = self.devicetree.resolveDevice(devspec,
- blkidTab=self.blkidTab)
- if device:
- self.mappings[name] = {"device": device,
- "keyfile": keyfile,
- "options": options}
-
- def populate(self):
- """ Populate the instance based on the device tree's contents. """
- for device in self.devicetree.devices.values():
- # XXX should we put them all in there or just the ones that
- # are part of a device containing swap or a filesystem?
- #
- # Put them all in here -- we can filter from FSSet
- if device.format.type != "luks":
- continue
-
- key_file = device.format.keyFile
- if not key_file:
- key_file = "none"
-
- options = device.format.options
- if not options:
- options = ""
-
- self.mappings[device.format.mapName] = {"device": device,
- "keyfile": key_file,
- "options": options}
-
- def crypttab(self):
- """ Write out /etc/crypttab """
- crypttab = ""
- for name in self.mappings:
- entry = self[name]
- crypttab += "%s UUID=%s %s %s\n" % (name,
- entry['device'].format.uuid,
- entry['keyfile'],
- entry['options'])
- return crypttab
-
- def __getitem__(self, key):
- return self.mappings[key]
-
- def get(self, key, default=None):
- return self.mappings.get(key, default)
+++ /dev/null
-#!/usr/bin/python
-
-import copy
-
-from devices import StorageDevice, PartitionDevice
-from formats import getFormat
-from errors import *
-from udev import *
-
-# The values are just hints as to the ordering.
-# Eg: fsmod and devmod ordering depends on the mod (shrink -v- grow)
-ACTION_TYPE_NONE = 0
-ACTION_TYPE_DESTROY = 1000
-ACTION_TYPE_RESIZE = 500
-ACTION_TYPE_MIGRATE = 250
-ACTION_TYPE_CREATE = 100
-
-action_strings = {ACTION_TYPE_NONE: "None",
- ACTION_TYPE_DESTROY: "Destroy",
- ACTION_TYPE_RESIZE: "Resize",
- ACTION_TYPE_MIGRATE: "Migrate",
- ACTION_TYPE_CREATE: "Create"}
-
-ACTION_OBJECT_NONE = 0
-ACTION_OBJECT_FORMAT = 1
-ACTION_OBJECT_DEVICE = 2
-
-object_strings = {ACTION_OBJECT_NONE: "None",
- ACTION_OBJECT_FORMAT: "Format",
- ACTION_OBJECT_DEVICE: "Device"}
-
-RESIZE_SHRINK = 88
-RESIZE_GROW = 89
-
-resize_strings = {RESIZE_SHRINK: "Shrink",
- RESIZE_GROW: "Grow"}
-
-def action_type_from_string(type_string):
- if type_string is None:
- return None
-
- for (k,v) in action_strings.items():
- if v.lower() == type_string.lower():
- return k
-
- return resize_type_from_string(type_string)
-
-def action_object_from_string(type_string):
- if type_string is None:
- return None
-
- for (k,v) in object_strings.items():
- if v.lower() == type_string.lower():
- return k
-
-def resize_type_from_string(type_string):
- if type_string is None:
- return None
-
- for (k,v) in resize_strings.items():
- if v.lower() == type_string.lower():
- return k
-
-class DeviceAction(object):
- """ An action that will be carried out in the future on a Device.
-
- These classes represent actions to be performed on devices or
- filesystems.
-
- The operand Device instance will be modified according to the
- action, but no changes will be made to the underlying device or
- filesystem until the DeviceAction instance's execute method is
- called. The DeviceAction instance's cancel method should reverse
- any modifications made to the Device instance's attributes.
-
- If the Device instance represents a pre-existing device, the
- constructor should call any methods or set any attributes that the
- action will eventually change. Device/DeviceFormat classes should verify
- that the requested modifications are reasonable and raise an
- exception if not.
-
- Only one action of any given type/object pair can exist for any
- given device at any given time. This is enforced by the
- DeviceTree.
-
- Basic usage:
-
- a = DeviceAction(dev)
- a.execute()
-
- OR
-
- a = DeviceAction(dev)
- a.cancel()
-
-
- XXX should we back up the device with a deep copy for forcibly
- cancelling actions?
-
- The downside is that we lose any checking or verification that
- would get done when resetting the Device instance's attributes to
- their original values.
-
- The upside is that we would be guaranteed to achieve a total
- reversal. No chance of, eg: resizes ending up altering Device
- size due to rounding or other miscalculation.
-"""
- type = ACTION_TYPE_NONE
- obj = ACTION_OBJECT_NONE
-
- def __init__(self, installer, device):
- self.installer = installer
- if not isinstance(device, StorageDevice):
- raise ValueError("arg 1 must be a StorageDevice instance")
- self.device = device
-
-
- def execute(self, intf=None):
- """ perform the action """
- pass
-
- def cancel(self):
- """ cancel the action """
- pass
-
- def isDestroy(self):
- return self.type == ACTION_TYPE_DESTROY
-
- def isCreate(self):
- return self.type == ACTION_TYPE_CREATE
-
- def isMigrate(self):
- return self.type == ACTION_TYPE_MIGRATE
-
- def isResize(self):
- return self.type == ACTION_TYPE_RESIZE
-
- def isShrink(self):
- return (self.type == ACTION_TYPE_RESIZE and self.dir == RESIZE_SHRINK)
-
- def isGrow(self):
- return (self.type == ACTION_TYPE_RESIZE and self.dir == RESIZE_GROW)
-
- def isDevice(self):
- return self.obj == ACTION_OBJECT_DEVICE
-
- def isFormat(self):
- return self.obj == ACTION_OBJECT_FORMAT
-
- def __str__(self):
- s = "%s %s" % (action_strings[self.type], object_strings[self.obj])
- if self.isResize():
- s += " (%s)" % resize_strings[self.dir]
- if self.isFormat():
- if self.device.format:
- fmt_type = self.device.format.type
- else:
- fmt_type = None
- s += " %s on" % fmt_type
- if self.isMigrate():
- pass
- s += " %s (%s)" % (self.device.name, self.device.type)
- return s
-
-class ActionCreateDevice(DeviceAction):
- """ Action representing the creation of a new device. """
- type = ACTION_TYPE_CREATE
- obj = ACTION_OBJECT_DEVICE
-
- def __init__(self, installer, device):
- # FIXME: assert device.fs is None
- DeviceAction.__init__(self, installer, device)
-
- def execute(self, intf=None):
- self.device.create(intf=intf)
-
-
-class ActionDestroyDevice(DeviceAction):
- """ An action representing the deletion of an existing device. """
- type = ACTION_TYPE_DESTROY
- obj = ACTION_OBJECT_DEVICE
-
- def __init__(self, installer, device):
- # XXX should we insist that device.fs be None?
- DeviceAction.__init__(self, installer, device)
- if device.exists:
- device.teardown()
-
- def execute(self, intf=None):
- self.device.destroy()
-
-
-class ActionResizeDevice(DeviceAction):
- """ An action representing the resizing of an existing device. """
- type = ACTION_TYPE_RESIZE
- obj = ACTION_OBJECT_DEVICE
-
- def __init__(self, installer, device, newsize):
- if device.currentSize == newsize:
- raise ValueError("new size same as old size")
-
- if not device.resizable:
- raise ValueError("device is not resizable")
-
- DeviceAction.__init__(self, installer, device)
- if newsize > device.currentSize:
- self.dir = RESIZE_GROW
- else:
- self.dir = RESIZE_SHRINK
- self.origsize = device.targetSize
- self.device.targetSize = newsize
-
- def execute(self, intf=None):
- self.device.resize(intf=intf)
-
- def cancel(self):
- self.device.targetSize = self.origsize
-
-
-class ActionCreateFormat(DeviceAction):
- """ An action representing creation of a new filesystem. """
- type = ACTION_TYPE_CREATE
- obj = ACTION_OBJECT_FORMAT
-
- def __init__(self, installer, device, format=None):
- DeviceAction.__init__(self, installer, device)
- if format:
- self.origFormat = device.format
- if self.device.format.exists:
- self.device.format.teardown()
- self.device.format = format
- else:
- self.origFormat = getFormat(None, installer=installer)
-
- def execute(self, intf=None):
- if isinstance(self.device, PartitionDevice):
- if self.format.partedFlag is not None:
- self.device.setFlag(self.format.partedFlag)
- self.device.disk.commit()
-
- udev_settle()
- self.device.setup()
- self.device.format.create(intf=intf,
- device=self.device.path,
- options=self.device.formatArgs)
- # Get the UUID now that the format is created
- udev_settle()
- self.device.updateSysfsPath()
- info = udev_get_block_device("/sys%s" % self.device.sysfsPath)
- self.device.format.uuid = udev_device_get_uuid(info)
-
- def cancel(self):
- self.device.format = self.origFormat
-
- @property
- def format(self):
- return self.device.format
-
-
-class ActionDestroyFormat(DeviceAction):
- """ An action representing the removal of an existing filesystem.
-
- XXX this seems unnecessary
- """
- type = ACTION_TYPE_DESTROY
- obj = ACTION_OBJECT_FORMAT
-
- def __init__(self, installer, device):
- DeviceAction.__init__(self, installer, device)
- # Save a deep copy of the device stack this format occupies.
- # This is necessary since the stack of devices and formats
- # required to get to this format may get yanked out from under
- # us between now and execute.
- self._device = copy.deepcopy(device)
- self.origFormat = self._device.format
- if device.format.exists:
- device.format.teardown()
- self.device.format = None
-
- def execute(self, intf=None):
- """ wipe the filesystem signature from the device """
- if self.origFormat:
- if isinstance(self.device, PartitionDevice) and \
- self.origFormat.partedFlag is not None:
- # unset partition flags and commit
- self.device.unsetFlag(self.origFormat.partedFlag)
- self.device.disk.commit()
- udev_settle()
-
- # set up our copy of the original device stack since the
- # reference we got may have had any number of things changed
- # since then (most notably, formats removed by this very
- # class' constructor)
- self._device.setup()
- self.origFormat.destroy()
- udev_settle()
- self._device.teardown()
-
- def cancel(self):
- self.device.format = self.origFormat
-
- @property
- def format(self):
- return self.origFormat
-
-
-class ActionResizeFormat(DeviceAction):
- """ An action representing the resizing of an existing filesystem.
-
- XXX Do we even want to support resizing of a filesystem without
- also resizing the device it resides on?
- """
- type = ACTION_TYPE_RESIZE
- obj = ACTION_OBJECT_FORMAT
-
- def __init__(self, installer, device, newsize):
- if device.targetSize == newsize:
- raise ValueError("new size same as old size")
-
- DeviceAction.__init__(self, installer, device)
- if newsize > device.format.currentSize:
- self.dir = RESIZE_GROW
- else:
- self.dir = RESIZE_SHRINK
- self.origSize = self.device.format.targetSize
- self.device.format.targetSize = newsize
-
- def execute(self, intf=None):
- self.device.setup()
- self.device.format.doResize(intf=intf)
-
- def cancel(self):
- self.device.format.targetSize = self.origSize
-
-class ActionMigrateFormat(DeviceAction):
- """ An action representing the migration of an existing filesystem. """
- type = ACTION_TYPE_MIGRATE
- obj = ACTION_OBJECT_FORMAT
-
- def __init__(self, installer, device):
- if not device.format.migratable or not device.format.exists:
- raise ValueError("device format is not migratable")
-
- DeviceAction.__init__(self, installer, device)
- self.device.format.migrate = True
-
- def execute(self, intf=None):
- self.device.setup()
- self.device.format.doMigrate(intf=intf)
-
- def cancel(self):
- self.device.format.migrate = False
+++ /dev/null
-#
-# crypto.py
-#
-# Copyright (C) 2009 Red Hat, Inc. All rights reserved.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-# Author(s): Dave Lehman <dlehman@redhat.com>
-# Martin Sivak <msivak@redhat.com>
-#
-
-import os
-from pycryptsetup import CryptSetup
-
-from ..errors import *
-
-def askyes(question):
- return True
-
-def dolog(priority, text):
- pass
-
-def is_luks(device):
- cs = CryptSetup(yesDialog = askyes, logFunc = dolog)
- return cs.isLuks(device)
-
-def luks_uuid(device):
- cs = CryptSetup(yesDialog = askyes, logFunc = dolog)
- return cs.luksUUID(device).strip()
-
-def luks_status(name):
- """True means active, False means inactive (or non-existent)"""
- cs = CryptSetup(yesDialog = askyes, logFunc = dolog)
- return cs.luksStatus(name)!=0
-
-def luks_format(device,
- passphrase=None, key_file=None,
- cipher=None, key_size=None):
- cs = CryptSetup(yesDialog = askyes, logFunc = dolog)
- key_file_unlink = False
-
- if passphrase:
- key_file = cs.prepare_passphrase_file(passphrase)
- key_file_unlink = True
- elif key_file and os.path.isfile(key_file):
- pass
- else:
- raise ValueError("luks_format requires either a passphrase or a key file")
-
- #None is not considered as default value and pycryptsetup doesn't accept it
- #so we need to filter out all Nones
- kwargs = {}
- kwargs["device"] = device
- if cipher: kwargs["cipher"] = cipher
- if key_file: kwargs["keyfile"] = key_file
- if key_size: kwargs["keysize"] = key_size
-
- rc = cs.luksFormat(**kwargs)
- if key_file_unlink: os.unlink(key_file)
-
- if rc:
- raise CryptoError("luks_format failed for '%s'" % device)
-
-def luks_open(device, name, passphrase=None, key_file=None):
- cs = CryptSetup(yesDialog = askyes, logFunc = dolog)
- key_file_unlink = False
-
- if passphrase:
- key_file = cs.prepare_passphrase_file(passphrase)
- key_file_unlink = True
- elif key_file and os.path.isfile(key_file):
- pass
- else:
- raise ValueError("luks_open requires either a passphrase or a key file")
-
- rc = cs.luksOpen(device = device, name = name, keyfile = key_file)
- if key_file_unlink: os.unlink(key_file)
- if rc:
- raise CryptoError("luks_open failed for %s (%s)" % (device, name))
-
-def luks_close(name):
- cs = CryptSetup(yesDialog = askyes, logFunc = dolog)
- rc = cs.luksClose(name)
- if rc:
- raise CryptoError("luks_close failed for %s" % name)
-
-def luks_add_key(device,
- new_passphrase=None, new_key_file=None,
- passphrase=None, key_file=None):
- cs = CryptSetup(yesDialog = askyes, logFunc = dolog)
- return cs.addKey(device, new_passphrase, new_key_file, passphrase, key_file)
-
-
-def luks_remove_key(device,
- del_passphrase=None, del_key_file=None,
- passphrase=None, key_file=None):
- cs = CryptSetup(yesDialog = askyes, logFunc = dolog)
- return cs.removeKey(device, del_passphrase, del_key_file, passphrase, key_file)
+++ /dev/null
-#!/usr/bin/python
-
-import os
-import re
-
-import util
-
-MAX_LV_SLOTS = 256
-
-def has_lvm():
- has_lvm = False
- for path in os.environ["PATH"].split(":"):
- if os.access("%s/lvm" % path, os.X_OK):
- has_lvm = True
- break
-
- if has_lvm:
- has_lvm = False
- for line in open("/proc/devices").readlines():
- if "device-mapper" in line.split():
- has_lvm = True
- break
-
- return has_lvm
-
-# Start config_args handling code
-#
-# Theoretically we can handle all that can be handled with the LVM --config
-# argument. For every time we call an lvm_cc (lvm compose config) funciton
-# we regenerate the config_args with all global info.
-config_args = [] # Holds the final argument list
-config_args_data = { "filterRejects": [], # regular expressions to reject.
- "filterAccepts": [] } # regexp to accept
-
-def _composeConfig():
- """lvm command accepts lvm.conf type arguments preceded by --config. """
- global config_args, config_args_data
- config_args = []
-
- filter_string = ""
- rejects = config_args_data["filterRejects"]
- # we don't need the accept for now.
- # accepts = config_args_data["filterAccepts"]
- # if len(accepts) > 0:
- # for i in range(len(rejects)):
- # filter_string = filter_string + ("\"a|%s|\", " % accpets[i])
-
- if len(rejects) > 0:
- for i in range(len(rejects)):
- filter_string = filter_string + ("\"r|%s|\"," % rejects[i])
-
- filter_string = " filter=[%s] " % filter_string.strip(",")
-
- # As we add config strings we should check them all.
- if filter_string == "":
- # Nothing was really done.
- return
-
- # devices_string can have (inside the brackets) "dir", "scan",
- # "preferred_names", "filter", "cache_dir", "write_cache_state",
- # "types", "sysfs_scan", "md_component_detection". see man lvm.conf.
- devices_string = " devices {%s} " % (filter_string) # strings can be added
- config_string = devices_string # more strings can be added.
- config_args = ["--config", config_string]
-
-def lvm_cc_addFilterRejectRegexp(regexp):
- """ Add a regular expression to the --config string."""
- global config_args_data
- config_args_data["filterRejects"].append(regexp)
-
- # compoes config once more.
- _composeConfig()
-
-def lvm_cc_resetFilter():
- global config_args_data
- config_args_data["filterRejects"] = []
- config_args_data["filterAccepts"] = []
-# End config_args handling code.
-
-# Names that should not be used int the creation of VGs
-lvm_vg_blacklist = []
-def blacklistVG(name):
- global lvm_vg_blacklist
- lvm_vg_blacklist.append(name)
-
-def getPossiblePhysicalExtents(floor=0):
- """Returns a list of integers representing the possible values for
- the physical extent of a volume group. Value is in KB.
-
- floor - size (in KB) of smallest PE we care about.
- """
-
- possiblePE = []
- curpe = 8
- while curpe <= 16384*1024:
- if curpe >= floor:
- possiblePE.append(curpe)
- curpe = curpe * 2
-
- return possiblePE
-
-def getMaxLVSize():
- """ Return the maximum size (in MB) of a logical volume. """
- if util.getArch() in ("x86_64",): #64bit architectures
- return (8*1024*1024*1024*1024) #Max is 8EiB (very large number..)
- else:
- return (16*1024*1024) #Max is 16TiB
-
-def safeLvmName(name):
- tmp = name.strip()
- tmp = tmp.replace("/", "_")
- tmp = re.sub("[^0-9a-zA-Z._]", "", tmp)
- tmp = tmp.lstrip("_")
-
- return tmp
+++ /dev/null
-import resource
-
-import util
-import os
-
-from ..errors import *
-
-import gettext
-_ = lambda x: gettext.ldgettext("pomona", x)
-
-def mkswap(device, label=''):
- argv = []
- if label:
- argv.extend(["-L", label])
- argv.append(device)
-
- rc = util.execWithRedirect("mkswap", argv,
- stderr = "/dev/tty5",
- stdout = "/dev/tty5",
- searchPath=1)
-
- if rc:
- raise SwapError("mkswap failed for '%s'" % device)
-
-def swapon(device, priority=None):
- pagesize = resource.getpagesize()
- buf = None
- if pagesize > 2048:
- num = pagesize
- else:
- num = 2048
-
- try:
- fd = os.open(device, os.O_RDONLY)
- buf = os.read(fd, num)
- except OSError:
- pass
- finally:
- try:
- os.close(fd)
- except (OSError, UnboundLocalError):
- pass
-
- if buf is not None and len(buf) == pagesize:
- sig = buf[pagesize - 10:]
- if sig == 'SWAP-SPACE':
- raise OldSwapError
- if sig == 'S1SUSPEND\x00' or sig == 'S2SUSPEND\x00':
- raise SuspendError
-
- argv = []
- if isinstance(priority, int) and 0 <= priority <= 32767:
- argv.extend(["-p", "%d" % priority])
- argv.append(device)
-
- rc = util.execWithRedirect("swapon",
- argv,
- stderr = "/dev/tty5",
- stdout = "/dev/tty5",
- searchPath=1)
-
- if rc:
- raise SwapError("swapon failed for '%s'" % device)
-
-def swapoff(device):
- rc = util.execWithRedirect("swapoff", [device],
- stderr = "/dev/tty5",
- stdout = "/dev/tty5",
- searchPath=1)
-
- if rc:
- raise SwapError("swapoff failed for '%s'" % device)
-
-def swapstatus(device):
- lines = open("/proc/swaps").readlines()
- status = False
- for line in lines:
- if not line.strip():
- continue
-
- if line.split()[0] == device:
- status = True
- break
-
- return status
+++ /dev/null
-#/usr/bin/python
-
-import copy
-import math
-import parted
-import _ped
-
-from errors import *
-from formats import get_device_format_class, getFormat
-from udev import *
-from util import notify_kernel, numeric_type
-
-def devicePathToName(devicePath):
- if devicePath.startswith("/dev/"):
- name = devicePath[5:]
- else:
- name = devicePath
-
- if name.startswith("mapper/"):
- name = name[7:]
-
- return name
-
-class Device(object):
- """ A generic device.
-
- Device instances know which devices they depend upon (parents
- attribute). They do not know which devices depend upon them, but
- they do know whether or not they have any dependent devices
- (isleaf attribute).
-
- A Device's setup method should set up all parent devices as well
- as the device itself. It should not run the resident format's
- setup method.
-
- Which Device types rely on their parents' formats being active?
- DMCryptDevice
-
- A Device's teardown method should accept the keyword argument
- recursive, which takes a boolean value and indicates whether or
- not to recursively close parent devices.
-
- A Device's create method should create all parent devices as well
- as the device itself. It should also run the Device's setup method
- after creating the device. The create method should not create a
- device's resident format.
-
- Which device type rely on their parents' formats to be created
- before they can be created/assembled?
- VolumeGroup
- DMCryptDevice
-
- A Device's destroy method should destroy any resident format
- before destroying the device itself.
-
- """
- _type = "generic device"
-
- def __init__(self, installer, name, parents=None, description=''):
- """ Create a Device instance.
-
- Arguments:
-
- name -- the device name (generally a device node's basename)
-
- Keyword Arguments:
-
- parents -- a list of required Device instances
- description -- a string describing the device
-
- """
- self.installer = installer
-
- self._name = name
- if parents is None:
- parents = []
- elif not isinstance(parents, list):
- raise ValueError("parents must be a list of Device instances")
- self.parents = parents
- self.kids = 0
- self.description = description
-
- for parent in self.parents:
- parent.addChild()
-
- def __deepcopy__(self, memo):
- """ Create a deep copy of a Device instance.
-
- We can't do copy.deepcopy on parted objects, which is okay.
- For these parted objects, we just do a shallow copy.
- """
- new = self.__class__.__new__(self.__class__)
- memo[id(self)] = new
- shallow_copy_attrs = ('partedDisk', '_partedDevice',
- '_partedPartition', '_origPartedDisk',
- '_raidSet', 'installer', 'screen')
- for (attr, value) in self.__dict__.items():
- if attr in shallow_copy_attrs:
- setattr(new, attr, copy.copy(value))
- else:
- setattr(new, attr, copy.deepcopy(value, memo))
-
- return new
-
- def removeChild(self):
- self.kids -= 1
-
- def addChild(self):
- self.kids += 1
-
- def setup(self, intf=None):
- """ Open, or set up, a device. """
- raise NotImplementedError("setup method not defined for Device")
-
- def teardown(self, recursive=None):
- """ Close, or tear down, a device. """
- raise NotImplementedError("teardown method not defined for Device")
-
- def create(self, intf=None):
- """ Create the device. """
- raise NotImplementedError("create method not defined for Device")
-
- def destroy(self):
- """ Destroy the device. """
- raise NotImplementedError("destroy method not defined for Device")
-
- def setupParents(self):
- """ Run setup method of all parent devices. """
- for parent in self.parents:
- parent.setup()
-
- def teardownParents(self, recursive=None):
- """ Run teardown method of all parent devices. """
- for parent in self.parents:
- parent.teardown(recursive=recursive)
-
- def createParents(self):
- """ Run create method of all parent devices. """
- self.installer.log.info("NOTE: recursive device creation disabled")
- for parent in self.parents:
- if not parent.exists:
- raise DeviceError("parent device does not exist")
- #parent.create()
-
- def dependsOn(self, dep):
- """ Return True if this device depends on dep. """
- # XXX does a device depend on itself?
- if dep in self.parents:
- return True
-
- for parent in self.parents:
- if parent.dependsOn(dep):
- return True
-
- return False
-
- @property
- def status(self):
- """ This device's status.
-
- For now, this should return a boolean:
- True the device is open and ready for use
- False the device is not open
- """
- return False
-
- @property
- def name(self):
- """ This device's name. """
- return self._name
-
- @property
- def isleaf(self):
- """ True if this device has no children. """
- return self.kids == 0
-
- @property
- def typeDescription(self):
- """ String describing the device type. """
- return self._type
-
- @property
- def type(self):
- """ Device type. """
- return self._type
-
- @property
- def mediaPresent(self):
- return True
-
-
-class StorageDevice(Device):
- """ A generic storage device.
-
- A fully qualified path to the device node can be obtained via the
- path attribute, although it is not guaranteed to be useful, or
- even present, unless the StorageDevice's setup method has been
- run.
-
- StorageDevice instances can optionally contain a filesystem,
- represented by an FS instance. A StorageDevice's create method
- should create a filesystem if one has been specified.
- """
- _type = "storage device"
- _devDir = "/dev"
- sysfsBlockDir = "class/block"
- _resizable = False
-
- def __init__(self, installer, device, format=None,
- size=None, major=None, minor=None,
- sysfsPath='', parents=None, exists=None):
- """ Create a StorageDevice instance.
-
- Arguments:
-
- device -- the device name (generally a device node's basename)
-
- Keyword Arguments:
-
- size -- the device's size (units/format TBD)
- major -- the device major
- minor -- the device minor
- sysfsPath -- sysfs device path
- format -- a DeviceFormat instance
- parents -- a list of required Device instances
- description -- a string describing the device
-
- """
- self.installer = installer
-
- # allow specification of individual parents
- if isinstance(parents, Device):
- parents = [parents]
-
- Device.__init__(self, installer, device, parents=parents)
-
- self.uuid = None
- self._format = None
- self._size = numeric_type(size)
- self.major = numeric_type(major)
- self.minor = numeric_type(minor)
- self.sysfsPath = sysfsPath
- self.exists = exists
-
- # this may be handy for disk, dmraid, mpath, mdraid
- self.diskLabel = None
-
- self.format = format
- self.fstabComment = ""
- self._targetSize = self._size
-
- self._partedDevice = None
-
- @property
- def partedDevice(self):
- if self.exists and self.status and not self._partedDevice:
- # We aren't guaranteed to be able to get a device. In
- # particular, built-in USB flash readers show up as devices but
- # do not always have any media present, so parted won't be able
- # to find a device.
- try:
- self._partedDevice = parted.Device(path=self.path)
- except _ped.DeviceException:
- pass
-
- return self._partedDevice
-
- def _getTargetSize(self):
- return self._targetSize
-
- def _setTargetSize(self, newsize):
- self._targetSize = newsize
-
- targetSize = property(lambda s: s._getTargetSize(),
- lambda s, v: s._setTargetSize(v),
- doc="Target size of this device")
-
- @property
- def path(self):
- """ Device node representing this device. """
- return "%s/%s" % (self._devDir, self.name)
-
- def updateSysfsPath(self):
- """ Update this device's sysfs path. """
- sysfsName = self.name.replace("/", "!")
- path = os.path.join("/sys", self.sysfsBlockDir, sysfsName)
- self.sysfsPath = os.path.realpath(path)[4:]
- self.installer.log.debug("%s sysfsPath set to %s" % (self.name, self.sysfsPath))
-
- @property
- def formatArgs(self):
- """ Device-specific arguments to format creation program. """
- return []
-
- @property
- def resizable(self):
- """ Can this type of device be resized? """
- return self._resizable and self.exists
-
- def notifyKernel(self):
- """ Send a 'change' uevent to the kernel for this device. """
- if not self.exists:
- self.installer.log.debug("Not sending change uevent for non-existent device")
- return
-
- if not self.status:
- self.installer.log.debug("Not sending change uevent for inactive device")
- return
-
- path = os.path.normpath("/sys/%s" % self.sysfsPath)
- try:
- notify_kernel(path, action="change")
- except Exception, e:
- self.installer.log.warning("Failed to notify kernel of change: %s" % e)
-
- @property
- def fstabSpec(self):
- spec = self.path
- if self.format and self.format.uuid:
- spec = "UUID=%s" % self.format.uuid
- return spec
-
- def resize(self, intf=None):
- """ Resize the device.
-
- New size should already be set.
- """
- raise NotImplementedError("resize method not defined for StorageDevice")
-
- def setup(self, intf=None):
- """ Open, or set up, a device. """
- if not self.exists:
- raise DeviceError("device has not been created")
-
- self.setupParents()
- for parent in self.parents:
- parent.format.setup()
-
- def teardown(self, recursive=None):
- """ Close, or tear down, a device. """
- if not self.exists and not recursive:
- raise DeviceError("device has not been created")
-
- if self.status and self.format.exists:
- self.format.teardown()
- udev_settle(timeout=10)
-
- if recursive:
- self.teardownParents(recursive=recursive)
-
- def _getSize(self):
- """ Get the device's size in MB, accounting for pending changes. """
- if self.exists and not self.mediaPresent:
- return 0
-
- if self.exists and self.partedDevice:
- self._size = self.currentSize
-
- size = self._size
- if self.exists and self.resizable and self.targetSize != size:
- size = self.targetSize
-
- return size
-
- def _setSize(self, newsize):
- """ Set the device's size to a new value. """
- if newsize > self.maxSize:
- raise DeviceError("device cannot be larger than %s MB" %
- (self.maxSize(),))
- self._size = newsize
-
- size = property(lambda x: x._getSize(),
- lambda x, y: x._setSize(y),
- doc="The device's size in MB, accounting for pending changes")
-
- @property
- def currentSize(self):
- """ The device's actual size. """
- size = 0
- if self.exists and self.partedDevice:
- size = self.partedDevice.getSize()
- elif self.exists:
- size = self._size
- return size
-
- @property
- def minSize(self):
- """ The minimum size this device can be. """
- if self.exists:
- self.setup()
-
- if self.format.minSize:
- return self.format.minSize
- else:
- return self.size
-
- @property
- def maxSize(self):
- """ The maximum size this device can be. """
- if self.format.maxSize > self.currentSize:
- return self.currentSize
- else:
- return self.format.maxSize
-
- @property
- def status(self):
- """ This device's status.
-
- For now, this should return a boolean:
- True the device is open and ready for use
- False the device is not open
- """
- if not self.exists:
- return False
- return os.access(self.path, os.W_OK)
-
- def _setFormat(self, format):
- """ Set the Device's format. """
- if not format:
- format = getFormat(None, installer=self.installer, device=self.path, exists=self.exists)
- if self._format and self._format.status:
- # FIXME: self.format.status doesn't mean much
- raise DeviceError("Cannot replace active format")
-
- self._format = format
-
- def _getFormat(self):
- return self._format
-
- format = property(lambda d: d._getFormat(),
- lambda d,f: d._setFormat(f),
- doc="The device's formatting.")
-
- def create(self, intf=None):
- """ Create the device. """
- if self.exists:
- raise DeviceError("device has already been created")
-
- self.createParents()
- self.setupParents()
- self.exists = True
- self.setup()
-
- def destroy(self):
- """ Destroy the device. """
- if not self.exists:
- raise DeviceError("device has not been created")
-
- if not self.isleaf:
- raise DeviceError("Cannot destroy non-leaf device")
-
- self.exists = False
-
- @property
- def removable(self):
- devpath = os.path.normpath("/sys/%s" % self.sysfsPath)
- remfile = os.path.normpath("%s/removable" % devpath)
- return (self.sysfsPath and os.path.exists(devpath) and
- os.access(remfile, os.R_OK) and
- open(remfile).readline().strip() == "1")
-
-class DiskDevice(StorageDevice):
- """ A disk """
- _type = "disk"
-
- def __init__(self, installer, device, format=None,
- size=None, major=None, minor=None, sysfsPath='', \
- parents=None, initcb=None, initlabel=None):
- """ Create a DiskDevice instance.
-
- Arguments:
-
- device -- the device name (generally a device node's basename)
-
- Keyword Arguments:
-
- size -- the device's size (units/format TBD)
- major -- the device major
- minor -- the device minor
- sysfsPath -- sysfs device path
- format -- a DeviceFormat instance
- parents -- a list of required Device instances
- removable -- whether or not this is a removable device
-
- initcb -- the call back to be used when initiating disk.
- initlabel -- whether to start with a fresh disklabel
-
-
- DiskDevices always exist.
- """
- self.installer = installer
- StorageDevice.__init__(self, self.installer, device, format=format,
- size=size, major=major, minor=minor, exists=True,
- sysfsPath=sysfsPath, parents=parents)
-
- self.partedDisk = None
-
- if self.partedDevice:
- if initlabel:
- self.partedDisk = self.freshPartedDisk()
- else:
- try:
- self.partedDisk = parted.Disk(device=self.partedDevice)
- except _ped.DiskLabelException:
- # if we have a cb function use it. else an error.
- if initcb is not None and initcb():
- self.partedDisk = parted.freshDisk(device=self.partedDevice, \
- ty = platform.getPlatform(None).diskType)
- else:
- raise DeviceUserDeniedFormatError("User prefered to not format.")
-
- # We save the actual state of the disk here. Before the first
- # modification (addPartition or removePartition) to the partition
- # table we reset self.partedPartition to this state so we can
- # perform the modifications one at a time.
- if self.partedDisk:
- self._origPartedDisk = self.partedDisk.duplicate()
- else:
- self._origPartedDisk = None
-
- def freshPartedDisk(self):
- labelType = platform.getPlatform(None).diskType
- return parted.freshDisk(device=self.partedDevice, ty=labelType)
-
- @property
- def mediaPresent(self):
- return self.partedDevice is not None
-
- @property
- def model(self):
- return getattr(self.partedDevice, "model", None)
-
- @property
- def size(self):
- """ The disk's size in MB """
- return super(DiskDevice, self).size
- #size = property(StorageDevice._getSize)
-
- def resetPartedDisk(self):
- """ Reset parted.Disk to reflect the actual layout of the disk. """
- self.partedDisk = self._origPartedDisk
-
- def removePartition(self, device):
- if not self.mediaPresent:
- raise DeviceError("Cannot remove partition from disk %s which has no media" % self.name)
-
- partition = self.partedDisk.getPartitionByPath(device.path)
- if partition:
- self.partedDisk.removePartition(partition)
-
- def addPartition(self, device):
- if not self.mediaPresent:
- raise DeviceError("cannot add partition to disk %s which has no media" % self.name)
-
- for part in self.partedDisk.partitions:
- self.installer.log.debug("Disk %s: partition %s has geom %s" % (self.name,
- part.getDeviceNodeName(),
- part.geometry))
-
- geometry = device.partedPartition.geometry
- constraint = parted.Constraint(exactGeom=geometry)
- partition = parted.Partition(disk=self.partedDisk,
- type=device.partedPartition.type,
- geometry=geometry)
- self.partedDisk.addPartition(partition, constraint=constraint)
-
- def probe(self):
- """ Probe for any missing information about this device.
-
- pyparted should be able to tell us anything we want to know.
- size, disklabel type, maybe even partition layout
- """
- if not self.diskLabel:
- self.installer.log.debug("Setting %s diskLabel to %s" % (self.name,
- self.partedDisk.type))
- self.diskLabel = self.partedDisk.type
-
- def commit(self, intf=None):
- """ Commit changes to the device. """
- if not self.mediaPresent:
- raise DeviceError("cannot commit to disk %s which has no media" % self.name)
-
- self.setupParents()
- self.setup()
-
- # give committing 5 tries, failing that, raise an exception
- attempt = 1
- maxTries = 5
- keepTrying = True
-
- while keepTrying and (attempt <= maxTries):
- try:
- self.partedDisk.commit()
- keepTrying = False
- except parted.DiskException as msg:
- self.installer.log.warning(msg)
- attempt += 1
-
- if keepTrying:
- raise DeviceError("cannot commit to disk %s after %d attempts" % (self.name, maxTries,))
-
- # commit makes the kernel re-scan the partition table
- udev_settle()
-
- def destroy(self):
- """ Destroy the device. """
- if not self.mediaPresent:
- raise DeviceError("cannot destroy disk %s which has no media" % self.name)
-
- self.partedDisk.deleteAllPartitions()
- # this is perhaps a separate operation (wiping the disklabel)
- self.partedDisk.clobber()
- self.partedDisk.commit()
- self.teardown()
-
- def setup(self, intf=None):
- """ Open, or set up, a device. """
- if not os.path.exists(self.path):
- raise DeviceError("device does not exist")
-
-class PartitionDevice(StorageDevice):
- """ A disk partition.
-
- On types and flags...
-
- We don't need to deal with numerical partition types at all. The
- only type we are concerned with is primary/logical/extended. Usage
- specification is accomplished through the use of flags, which we
- will set according to the partition's format.
- """
- _type = "partition"
- _resizable = True
-
- def __init__(self, installer, name, format=None,
- size=None, grow=False, maxsize=None,
- major=None, minor=None, bootable=None,
- sysfsPath='', parents=None, exists=None,
- partType=None, primary=False, weight=0):
- """ Create a PartitionDevice instance.
-
- Arguments:
-
- name -- the device name (generally a device node's basename)
-
- Keyword Arguments:
-
- exists -- indicates whether this is an existing device
- format -- the device's format (DeviceFormat instance)
-
- For existing partitions:
-
- parents -- the disk that contains this partition
- major -- the device major
- minor -- the device minor
- sysfsPath -- sysfs device path
-
- For new partitions:
-
- partType -- primary,extended,&c (as parted constant)
- grow -- whether or not to grow the partition
- maxsize -- max size for growable partitions (in MB)
- size -- the device's size (in MB)
- bootable -- whether the partition is bootable
- parents -- a list of potential containing disks
- weight -- an initial sorting weight to assign
- """
- self.req_disks = []
- self.req_partType = None
- self.req_primary = None
- self.req_grow = None
- self.req_bootable = None
- self.req_size = 0
- self.req_base_size = 0
- self.req_max_size = 0
- self.req_base_weight = 0
-
- self._bootable = False
-
- StorageDevice.__init__(self, installer, name, format=format, size=size,
- major=major, minor=minor, exists=exists,
- sysfsPath=sysfsPath, parents=parents)
-
- if not exists:
- # this is a request, not a partition -- it has no parents
- self.req_disks = self.parents[:]
- for dev in self.parents:
- dev.removeChild()
- self.parents = []
-
- # FIXME: Validate partType, but only if this is a new partition
- # Otherwise, overwrite it with the partition's type.
- self._partType = None
- self.partedFlags = {}
- self._partedPartition = None
-
- # FIXME: Validate size, but only if this is a new partition.
- # For existing partitions we will get the size from
- # parted.
-
- if self.exists:
- #self.partedPartition = parted.getPartitionByName(self.path)
- self._partedPartition = self.disk.partedDisk.getPartitionByPath(self.path)
- if not self._partedPartition:
- raise DeviceError("cannot find parted partition instance")
-
- # collect information about the partition from parted
- self.probe()
- else:
- # XXX It might be worthwhile to create a shit-simple
- # PartitionRequest class and pass one to this constructor
- # for new partitions.
- self.req_name = name
- self.req_partType = partType
- self.req_primary = primary
- self.req_max_size = numeric_type(maxsize)
- self.req_grow = grow
- self.req_bootable = bootable
-
- # req_size may be manipulated in the course of partitioning
- self.req_size = self._size
-
- # req_base_size will always remain constant
- self.req_base_size = self._size
-
- self.req_base_weight = weight
-
- def _setTargetSize(self, newsize):
- if newsize != self.currentSize:
- # change this partition's geometry in-memory so that other
- # partitioning operations can complete (e.g., autopart)
- self._targetSize = newsize
- disk = self.disk.partedDisk
-
- # resize the partition's geometry in memory
- (constraint, geometry) = self._computeResize(self.partedPartition)
- disk.setPartitionGeometry(partition=self.partedPartition,
- constraint=constraint,
- start=geometry.start, end=geometry.end)
-
- @property
- def path(self):
- """ Device node representing this device. """
- if not self.parents:
- # Bogus, but code in various places compares devices by path
- # So we must return something unique
- return self.name
-
- return "%s/%s" % (self.parents[0]._devDir, self.name)
-
- @property
- def partType(self):
- """ Get the partition's type (as parted constant). """
- try:
- ptype = self.partedPartition.type
- except AttributeError:
- ptype = self._partType
-
- if not self.exists and ptype is None:
- ptype = self.req_partType
-
- return ptype
-
- @property
- def isExtended(self):
- return self.partType & parted.PARTITION_EXTENDED
-
- @property
- def isLogical(self):
- return self.partType & parted.PARTITION_LOGICAL
-
- @property
- def isPrimary(self):
- return self.partType == parted.PARTITION_NORMAL
-
- @property
- def isProtected(self):
- return self.partType & parted.PARTITION_PROTECTED
-
- def _getPartedPartition(self):
- return self._partedPartition
-
- def _setPartedPartition(self, partition):
- """ Set this PartitionDevice's parted Partition instance. """
- if partition is None:
- path = None
- elif isinstance(partition, parted.Partition):
- path = partition.path
- else:
- raise ValueError("partition must be a parted.Partition instance")
-
- self._partedPartition = partition
- self.updateName()
-
- partedPartition = property(lambda d: d._getPartedPartition(),
- lambda d,p: d._setPartedPartition(p))
-
- def _getWeight(self):
- return self.req_base_weight
-
- def _setWeight(self, weight):
- self.req_base_weight = weight
-
- weight = property(lambda d: d._getWeight(),
- lambda d,w: d._setWeight(w))
-
- def updateSysfsPath(self):
- """ Update this device's sysfs path. """
- if not self.parents:
- self.sysfsPath = ''
-
- elif self.parents[0]._devDir == "/dev/mapper":
- dm_node = dm.dm_node_from_name(self.name)
- path = os.path.join("/sys", self.sysfsBlockDir, dm_node)
- self.sysfsPath = os.path.realpath(path)[4:]
-
- else:
- StorageDevice.updateSysfsPath(self)
-
- def updateName(self):
- if self.partedPartition is None:
- self._name = self.req_name
- else:
- self._name = \
- devicePathToName(self.partedPartition.getDeviceNodeName())
-
- def dependsOn(self, dep):
- """ Return True if this device depends on dep. """
- if isinstance(dep, PartitionDevice) and dep.isExtended and self.isLogical:
- return True
-
- return Device.dependsOn(self, dep)
-
- def _setFormat(self, format):
- """ Set the Device's format. """
- StorageDevice._setFormat(self, format)
-
- def _setBootable(self, bootable):
- """ Set the bootable flag for this partition. """
- if self.partedPartition:
- if self.flagAvailable(parted.PARTITION_BOOT):
- if bootable:
- self.setFlag(parted.PARTITION_BOOT)
- else:
- self.unsetFlag(parted.PARTITION_BOOT)
- else:
- raise DeviceError(_("boot flag not available for this "
- "partition"))
-
- self._bootable = bootable
- else:
- self.req_bootable = bootable
-
- def _getBootable(self):
- return self._bootable or self.req_bootable
-
- bootable = property(_getBootable, _setBootable)
-
- def flagAvailable(self, flag):
- if not self.partedPartition:
- return
-
- return self.partedPartition.isFlagAvailable(flag)
-
- def getFlag(self, flag):
- if not self.partedPartition or not self.flagAvailable(flag):
- return
-
- return self.partedPartition.getFlag(flag)
-
- def setFlag(self, flag):
- if not self.partedPartition or not self.flagAvailable(flag):
- return
-
- self.partedPartition.setFlag(flag)
-
- def unsetFlag(self, flag):
- if not self.partedPartition or not self.flagAvailable(flag):
- return
-
- self.partedPartition.unsetFlag(flag)
-
- def probe(self):
- """ Probe for any missing information about this device.
-
- size, partition type, flags
- """
- if not self.exists:
- return
-
- # this is in MB
- self._size = self.partedPartition.getSize()
- self.targetSize = self._size
-
- self._partType = self.partedPartition.type
-
- self._bootable = self.getFlag(parted.PARTITION_BOOT)
-
- def create(self, intf=None):
- """ Create the device. """
- if self.exists:
- raise DeviceError("device already exists")
-
- self.createParents()
- self.setupParents()
-
- self.disk.addPartition(self)
- self.disk.commit()
-
- self.partedPartition = self.disk.partedDisk.getPartitionByPath(self.path)
-
- self.exists = True
- self.setup()
-
- def _computeResize(self, partition):
- # compute new size for partition
- currentGeom = partition.geometry
- currentDev = currentGeom.device
- newLen = long(self.targetSize * 1024 * 1024) / currentDev.sectorSize
- newGeometry = parted.Geometry(device=currentDev,
- start=currentGeom.start,
- length=newLen)
- constraint = parted.Constraint(exactGeom=newGeometry)
-
- return (constraint, newGeometry)
-
- def resize(self, intf=None):
- """ Resize the device.
-
- self.targetSize must be set to the new size.
- """
- if self.targetSize != self.currentSize:
- # partedDisk has been restored to _origPartedDisk, so
- # recalculate resize geometry because we may have new
- # partitions on the disk, which could change constraints
- partition = self.disk.partedDisk.getPartitionByPath(self.path)
- (constraint, geometry) = self._computeResize(partition)
-
- self.disk.partedDisk.setPartitionGeometry(partition=partition,
- constraint=constraint,
- start=geometry.start,
- end=geometry.end)
-
- self.disk.commit()
- self.notifyKernel()
-
- def destroy(self):
- """ Destroy the device. """
- if not self.exists:
- raise DeviceError("device has not been created")
-
- if not self.sysfsPath:
- return
-
- if not self.isleaf:
- raise DeviceError("Cannot destroy non-leaf device")
-
- self.setupParents()
- self.disk.removePartition(self)
- self.disk.commit()
-
- self.exists = False
-
- def _getSize(self):
- """ Get the device's size. """
- size = self._size
- if self.partedPartition:
- # this defaults to MB
- size = self.partedPartition.getSize()
- return size
-
- def _setSize(self, newsize):
- """ Set the device's size (for resize, not creation).
-
- Arguments:
-
- newsize -- the new size (in MB)
-
- """
- if not self.exists:
- raise DeviceError("device does not exist")
-
- if newsize > self.disk.size:
- raise ValueError("partition size would exceed disk size")
-
- # this defaults to MB
- maxAvailableSize = self.partedPartition.getMaxAvailableSize()
-
- if newsize > maxAvailableSize:
- raise ValueError("new size is greater than available space")
-
- # now convert the size to sectors and update the geometry
- geometry = self.partedPartition.geometry
- physicalSectorSize = geometry.device.physicalSectorSize
-
- new_length = (newsize * (1024 * 1024)) / physicalSectorSize
- geometry.length = new_length
-
- def _getDisk(self):
- """ The disk that contains this partition."""
- try:
- disk = self.parents[0]
- except IndexError:
- disk = None
- return disk
-
- def _setDisk(self, disk):
- """Change the parent.
-
- Setting up a disk is not trivial. It has the potential to change
- the underlying object. If necessary we must also change this object.
- """
- if self.disk:
- self.disk.removeChild()
-
- if disk:
- self.parents = [disk]
- disk.addChild()
- else:
- self.parents = []
-
- disk = property(lambda p: p._getDisk(), lambda p,d: p._setDisk(d))
-
- @property
- def maxSize(self):
- """ The maximum size this partition can be. """
- # XXX: this is MB by default
- maxPartSize = self.partedPartition.getMaxAvailableSize()
-
- if self.format.maxSize > maxPartSize:
- return maxPartSize
- else:
- return self.format.maxSize
-
-class OpticalDevice(StorageDevice):
- """ An optical drive, eg: cdrom, dvd+r, &c.
-
- XXX Is this useful?
- """
- _type = "cdrom"
-
- def __init__(self, installer, name, major=None, minor=None, exists=None,
- format=None, parents=None, sysfsPath=''):
- StorageDevice.__init__(self, installer, name, format=format,
- major=major, minor=minor, exists=True,
- parents=parents, sysfsPath=sysfsPath)
-
- @property
- def mediaPresent(self):
- """ Return a boolean indicating whether or not the device contains
- media.
- """
- if not self.exists:
- raise DeviceError("device has not been created", self.path)
-
- try:
- fd = os.open(self.path, os.O_RDONLY)
- except OSError as e:
- # errno 123 = No medium found
- if e.errno == 123:
- return False
- else:
- return True
- else:
- os.close(fd)
- return True
-
- def eject(self):
- """ Eject the drawer. """
- #import _isys
-
- if not self.exists:
- raise DeviceError("device has not been created", self.path)
-
- # Make a best effort attempt to do the eject. If it fails, it's not
- # critical.
- fd = os.open(self.path, os.O_RDONLY | os.O_NONBLOCK)
-
- #try:
- # _isys.ejectcdrom(fd)
- #except SystemError as e:
- # log.warning("error ejecting cdrom %s: %s" % (self.name, e))
-
- os.close(fd)
-
-class DMDevice(StorageDevice):
- """ A device-mapper device """
- _type = "dm"
- _devDir = "/dev/mapper"
-
- def __init__(self, installer, name, format=None, size=None, dmUuid=None,
- target=None, exists=None, parents=None, sysfsPath=''):
- """ Create a DMDevice instance.
-
- Arguments:
-
- name -- the device name (generally a device node's basename)
-
- Keyword Arguments:
-
- target -- the device-mapper target type (string)
- size -- the device's size (units/format TBD)
- dmUuid -- the device's device-mapper UUID
- sysfsPath -- sysfs device path
- format -- a DeviceFormat instance
- parents -- a list of required Device instances
- exists -- indicates whether this is an existing device
- """
- StorageDevice.__init__(self, installer, name, format=format, size=size,
- exists=exists,
- parents=parents, sysfsPath=sysfsPath)
- self.target = target
- self.dmUuid = dmUuid
-
- def __str__(self):
- s = StorageDevice.__str__(self)
- s += (" target = %(target)s dmUuid = %(dmUuid)s" %
- {"target": self.target, "dmUuid": self.dmUuid})
- return s
-
- @property
- def fstabSpec(self):
- """ Return the device specifier for use in /etc/fstab. """
- return self.path
-
- def updateSysfsPath(self):
- """ Update this device's sysfs path. """
- if not self.exists:
- raise DeviceError("device has not been created")
-
- if self.status:
- dm_node = self.getDMNode()
- path = os.path.join("/sys", self.sysfsBlockDir, dm_node)
- self.sysfsPath = os.path.realpath(path)[4:]
- else:
- self.sysfsPath = ''
-
- #def getTargetType(self):
- # return dm.getDmTarget(name=self.name)
-
- def getDMNode(self):
- """ Return the dm-X (eg: dm-0) device node for this device. """
- if not self.exists:
- raise DeviceError("device has not been created")
-
- return dm.dm_node_from_name(self.name)
-
- def _setName(self, name):
- """ Set the device's map name. """
- if self.status:
- raise DeviceError("device is active")
-
- self._name = name
- #self.sysfsPath = "/dev/disk/by-id/dm-name-%s" % self.name
-
- name = property(lambda d: d._name,
- lambda d,n: d._setName(n))
-
-
-class LVMVolumeGroupDevice(DMDevice):
- """ An LVM Volume Group
-
- XXX Maybe this should inherit from StorageDevice instead of
- DMDevice since there's no actual device.
- """
- _type = "lvmvg"
-
- def __init__(self, installer, name, parents, size=None, free=None,
- peSize=None, peCount=None, peFree=None, pvCount=None,
- lvNames=[], uuid=None, exists=None, sysfsPath=''):
- """ Create a LVMVolumeGroupDevice instance.
-
- Arguments:
-
- name -- the device name (generally a device node's basename)
- parents -- a list of physical volumes (StorageDevice)
-
- Keyword Arguments:
-
- peSize -- physical extent size (in MB)
- exists -- indicates whether this is an existing device
- sysfsPath -- sysfs device path
-
- For existing VG's only:
-
- size -- the VG's size (in MB)
- free -- amount of free space in the VG
- peFree -- number of free extents
- peCount -- total number of extents
- pvCount -- number of PVs in this VG
- lvNames -- the names of this VG's LVs
- uuid -- the VG's UUID
-
- """
- self.pvClass = get_device_format_class("lvmpv")
- if not self.pvClass:
- raise DeviceError("cannot find 'lvmpv' class")
-
- if isinstance(parents, list):
- for dev in parents:
- if not isinstance(dev.format, self.pvClass):
- raise ValueError("constructor requires a list of PVs")
- elif not isinstance(parents.format, self.pvClass):
- raise ValueError("constructor requires a list of PVs")
-
- DMDevice.__init__(self, installer, name, parents=parents,
- exists=exists, sysfsPath=sysfsPath)
-
- self.uuid = uuid
- self.free = numeric_type(free)
- self.peSize = numeric_type(peSize)
- self.peCount = numeric_type(peCount)
- self.peFree = numeric_type(peFree)
- self.pvCount = numeric_type(pvCount)
- self.lvNames = lvNames
-
- # circular references, here I come
- self._lvs = []
-
- # TODO: validate peSize if given
- if not self.peSize:
- self.peSize = 4.0 # MB
-
- #self.probe()
-
- def __str__(self):
- s = DMDevice.__str__(self)
- s += (" free = %(free)s PE Size = %(peSize)s PE Count = %(peCount)s\n"
- " PE Free = %(peFree)s PV Count = %(pvCount)s\n"
- " LV Names = %(lvNames)s modified = %(modified)s\n"
- " extents = %(extents)s free space = %(freeSpace)s\n"
- " free extents = %(freeExtents)s\n"
- " PVs = %(pvs)s\n"
- " LVs = %(lvs)s" %
- {"free": self.free, "peSize": self.peSize, "peCount": self.peCount,
- "peFree": self.peFree, "pvCount": self.pvCount,
- "lvNames": self.lvNames, "modified": self.isModified,
- "extents": self.extents, "freeSpace": self.freeSpace,
- "freeExtents": self.freeExtents, "pvs": self.pvs, "lvs": self.lvs})
- return s
-
- def probe(self):
- """ Probe for any information about this device. """
- if not self.exists:
- raise DeviceError("device has not been created")
-
- @property
- def status(self):
- """ The device's status (True means active). """
- if not self.exists:
- return False
-
- # certainly if any of this VG's LVs are active then so are we
- for lv in self.lvs:
- if lv.status:
- return True
-
- # if any of our PVs are not active then we cannot be
- for pv in self.pvs:
- if not pv.status:
- return False
-
- # if we are missing some of our PVs we cannot be active
- if len(self.pvs) != self.pvCount:
- return False
-
- return True
-
- def _addDevice(self, device):
- """ Add a new physical volume device to the volume group.
-
- XXX This is for use by device probing routines and is not
- intended for modification of the VG.
- """
- if not self.exists:
- raise DeviceError("device does not exist")
-
- if not isinstance(device.format, self.pvClass):
- raise ValueError("addDevice requires a PV arg")
-
- if self.uuid and device.format.vgUuid != self.uuid:
- raise ValueError("UUID mismatch")
-
- if device in self.pvs:
- raise ValueError("device is already a member of this VG")
-
- self.parents.append(device)
- device.addChild()
-
- # now see if the VG can be activated
- if len(self.parents) == self.pvCount:
- self.setup()
-
- def _removeDevice(self, device):
- """ Remove a physical volume from the volume group.
-
- This is for cases like clearing of preexisting partitions.
- """
- try:
- self.parents.remove(device)
- except ValueError, e:
- raise ValueError("cannot remove non-member PV device from VG")
-
- device.removeChild()
-
- def setup(self, intf=None):
- """ Open, or set up, a device.
-
- XXX we don't do anything like "vgchange -ay" because we don't
- want all of the LVs activated, just the VG itself.
- """
- if not self.exists:
- raise DeviceError("device has not been created")
-
- if self.status:
- return
-
- if len(self.parents) < self.pvCount:
- raise DeviceError("cannot activate VG with missing PV(s)")
-
- self.setupParents()
-
- def teardown(self, recursive=None):
- """ Close, or tear down, a device. """
- if not self.exists and not recursive:
- raise DeviceError("device has not been created")
-
- if self.status:
- lvm.vgdeactivate(self.name)
-
- if recursive:
- self.teardownParents(recursive=recursive)
-
- def create(self, intf=None):
- """ Create the device. """
- if self.exists:
- raise DeviceError("device already exists")
-
- pv_list = []
- #for pv in self.parents:
- # This is a little bit different from other devices in that
- # for VG we need the PVs to be formatted before we can create
- # the VG.
- # pv.create()
- # pv.format.create()
- # pv_list.append(pv.path)
- pv_list = [pv.path for pv in self.parents]
- self.createParents()
- self.setupParents()
- lvm.vgcreate(self.name, pv_list, self.peSize)
- # FIXME set / update self.uuid here
- self.exists = True
- self.setup()
-
- def destroy(self):
- """ Destroy the device. """
- if not self.exists:
- raise DeviceError("device has not been created")
-
- # set up the pvs since lvm needs access to them to do the vgremove
- self.setupParents()
-
- # this sometimes fails for some reason.
- try:
- lvm.vgreduce(self.name, [], rm=True)
- lvm.vgremove(self.name)
- except lvm.LVMError:
- raise DeviceError("Could not completely remove VG %s" % self.name)
- finally:
- self.notifyKernel()
- self.exists = False
-
- def reduce(self, pv_list):
- """ Remove the listed PVs from the VG. """
- if not self.exists:
- raise DeviceError("device has not been created")
-
- lvm.vgreduce(self.name, pv_list)
- # XXX do we need to notify the kernel?
-
- def _addLogVol(self, lv):
- """ Add an LV to this VG. """
- if lv in self._lvs:
- raise ValueError("lv is already part of this vg")
-
- # verify we have the space, then add it
- # do not verify for growing vg (because of ks)
- if not lv.exists and \
- not [pv for pv in self.pvs if getattr(pv, "req_grow", None)] and \
- lv.size > self.freeSpace:
- raise DeviceError("new lv is too large to fit in free space")
-
- self._lvs.append(lv)
-
- def _removeLogVol(self, lv):
- """ Remove an LV from this VG. """
- if lv not in self.lvs:
- raise ValueError("specified lv is not part of this vg")
-
- self._lvs.remove(lv)
-
- def _addPV(self, pv):
- """ Add a PV to this VG. """
- if pv in self.pvs:
- raise ValueError("pv is already part of this vg")
-
- # for the time being we will not allow vgextend
- if self.exists:
- raise DeviceError("cannot add pv to existing vg")
-
- self.parents.append(pv)
- pv.addChild()
-
- def _removePV(self, pv):
- """ Remove an PV from this VG. """
- if not pv in self.pvs:
- raise ValueError("specified pv is not part of this vg")
-
- # for the time being we will not allow vgreduce
- if self.exists:
- raise DeviceError("cannot remove pv from existing vg")
-
- self.parents.remove(pv)
- pv.removeChild()
-
- # We can't rely on lvm to tell us about our size, free space, &c
- # since we could have modifications queued, unless the VG and all of
- # its PVs already exist.
- #
- # -- liblvm may contain support for in-memory devices
-
- @property
- def isModified(self):
- """ Return True if the VG has changes queued that LVM is unaware of. """
- modified = True
- if self.exists and not filter(lambda d: not d.exists, self.pvs):
- modified = False
-
- return modified
-
- @property
- def size(self):
- """ The size of this VG """
- # TODO: just ask lvm if isModified returns False
-
- # sum up the sizes of the PVs and align to pesize
- size = 0
- for pv in self.pvs:
- size += max(0, self.align(pv.size - pv.format.peStart))
-
- return size
-
- @property
- def extents(self):
- """ Number of extents in this VG """
- # TODO: just ask lvm if isModified returns False
-
- return self.size / self.peSize
-
- @property
- def freeSpace(self):
- """ The amount of free space in this VG (in MB). """
- # TODO: just ask lvm if isModified returns False
-
- # total the sizes of any LVs
- used = 0
- size = self.size
- self.installer.log.debug("%s size is %dMB" % (self.name, size))
- for lv in self.lvs:
- self.installer.log.debug("lv %s (%s) uses %dMB" % (lv.name, lv, lv.size))
- used += self.align(lv.size, roundup=True)
-
- free = self.size - used
- self.installer.log.debug("vg %s has %dMB free" % (self.name, free))
- return free
-
- @property
- def freeExtents(self):
- """ The number of free extents in this VG. """
- # TODO: just ask lvm if isModified returns False
- return self.freeSpace / self.peSize
-
- def align(self, size, roundup=None):
- """ Align a size to a multiple of physical extent size. """
- size = numeric_type(size)
-
- if roundup:
- round = math.ceil
- else:
- round = math.floor
-
- # we want Kbytes as a float for our math
- size *= 1024.0
- pesize = self.peSize * 1024.0
- return long((round(size / pesize) * pesize) / 1024)
-
- @property
- def pvs(self):
- """ A list of this VG's PVs """
- return self.parents[:] # we don't want folks changing our list
-
- @property
- def lvs(self):
- """ A list of this VG's LVs """
- return self._lvs[:] # we don't want folks changing our list
-
- @property
- def complete(self):
- """Check if the vg has all its pvs in the system
- Return True if complete.
- """
- return len(self.pvs) == self.pvCount or not self.exists
-
-class LVMLogicalVolumeDevice(DMDevice):
- """ An LVM Logical Volume """
- _type = "lvmlv"
- _resizable = True
-
- def __init__(self, installer, name, vgdev, size=None, uuid=None,
- format=None, exists=None, sysfsPath='',
- grow=None, maxsize=None, percent=None):
- """ Create a LVMLogicalVolumeDevice instance.
-
- Arguments:
-
- name -- the device name (generally a device node's basename)
- vgdev -- volume group (LVMVolumeGroupDevice instance)
-
- Keyword Arguments:
-
- size -- the device's size (in MB)
- uuid -- the device's UUID
- sysfsPath -- sysfs device path
- format -- a DeviceFormat instance
- exists -- indicates whether this is an existing device
-
- For new (non-existent) LVs only:
-
- grow -- whether to grow this LV
- maxsize -- maximum size for growable LV (in MB)
- percent -- percent of VG space to take
-
- """
- if isinstance(vgdev, list):
- if len(vgdev) != 1:
- raise ValueError("constructor requires a single LVMVolumeGroupDevice instance")
- elif not isinstance(vgdev[0], LVMVolumeGroupDevice):
- raise ValueError("constructor requires a LVMVolumeGroupDevice instance")
- elif not isinstance(vgdev, LVMVolumeGroupDevice):
- raise ValueError("constructor requires a LVMVolumeGroupDevice instance")
- DMDevice.__init__(self, installer, name, size=size, format=format,
- sysfsPath=sysfsPath, parents=vgdev,
- exists=exists)
-
- self.uuid = uuid
-
- self.req_grow = None
- self.req_max_size = 0
- self.req_size = 0
- self.req_percent = 0
-
- if not self.exists:
- self.req_grow = grow
- self.req_max_size = numeric_type(maxsize)
- # XXX should we enforce that req_size be pe-aligned?
- self.req_size = self._size
- self.req_percent = numeric_type(percent)
-
- # here we go with the circular references
- self.vg._addLogVol(self)
-
- def __str__(self):
- s = DMDevice.__str__(self)
- s += (" VG device = %(vgdev)r percent = %(percent)s" %
- {"vgdev": self.vg, "percent": self.req_percent})
- return s
-
- def _setSize(self, size):
- size = self.vg.align(numeric_type(size))
- self.installer.log.debug("Trying to set lv %s size to %dMB" % (self.name, size))
- if size <= (self.vg.freeSpace + self._size):
- self._size = size
- self.targetSize = size
- else:
- self.installer.log.debug("Failed to set size: %dMB short" % (size - (self.vg.freeSpace + self._size),))
- raise ValueError("Not enough free space in volume group")
-
- size = property(StorageDevice._getSize, _setSize)
-
- @property
- def vg(self):
- """ This Logical Volume's Volume Group. """
- return self.parents[0]
-
- @property
- def path(self):
- """ Device node representing this device. """
- # Thank you lvm for this lovely hack.
- return "%s/%s-%s" % (self._devDir, self.vg.name.replace("-","--"),
- self._name.replace("-","--"))
-
- def getDMNode(self):
- """ Return the dm-X (eg: dm-0) device node for this device. """
- # Thank you lvm for this lovely hack.
- if not self.exists:
- raise DeviceError("Device has not been created", self.path)
-
- return dm.dm_node_from_name("%s-%s" % (self.vg.name.replace("-","--"), \
- self._name.replace("-","--")))
-
- @property
- def name(self):
- """ This device's name. """
- return "%s-%s" % (self.vg.name, self._name)
-
- @property
- def lvname(self):
- """ The LV's name (not including VG name). """
- return self._name
-
- @property
- def complete(self):
- """ Test if vg exits and if it has all pvs. """
- return self.vg.complete
-
- def setup(self, intf=None):
- """ Open, or set up, a device. """
- if not self.exists:
- raise DeviceError("Device has not been created", self.path)
-
- if self.status:
- return
-
- self.vg.setup()
- lvm.lvactivate(self.vg.name, self._name)
-
- # we always probe since the device may not be set up when we want
- # information about it
- self._size = self.currentSize
-
- def teardown(self, recursive=None):
- """ Close, or tear down, a device. """
- if not self.exists and not recursive:
- raise DeviceError("Device has not been created", self.path)
-
- if self.status and self.format.exists:
- self.format.teardown()
- udev_settle(timeout=10)
-
- if self.status:
- lvm.lvdeactivate(self.vg.name, self._name)
-
- if recursive:
- # It's likely that teardown of a VG will fail due to other
- # LVs being active (filesystems mounted, &c), so don't let
- # it bring everything down.
- try:
- self.vg.teardown(recursive=recursive)
- except Exception as e:
- log.debug("vg %s teardown failed; continuing" % self.vg.name)
-
- def create(self, intf=None):
- """ Create the device. """
- if self.exists:
- raise DeviceError("Device already exists", self.path)
-
- self.createParents()
- self.setupParents()
-
- # should we use --zero for safety's sake?
- lvm.lvcreate(self.vg.name, self._name, self.size)
- # FIXME set / update self.uuid here
- self.exists = True
- self.setup()
-
- def destroy(self):
- """ Destroy the device. """
- if not self.exists:
- raise DeviceError("Device has not been created", self.path)
-
- self.teardown()
- # set up the vg's pvs so lvm can remove the lv
- self.vg.setupParents()
- lvm.lvremove(self.vg.name, self._name)
- self.exists = False
-
- def resize(self, intf=None):
- # XXX resize format probably, right?
- if not self.exists:
- raise DeviceError("Device has not been created", self.path)
-
- # Setup VG parents (in case they are dmraid partitions for example)
- self.vg.setupParents()
-
- if self.format.exists:
- self.format.teardown()
-
- udev_settle(timeout=10)
- lvm.lvresize(self.vg.name, self._name, self.size)
+++ /dev/null
-#!/usr/bin/python
-
-import os
-import block
-
-import formats
-
-from devicelibs import lvm
-from devices import *
-from errors import *
-from udev import *
-
-class DeviceTree:
- def __init__(self, installer):
- self.installer = installer
- self.storage = self.installer.ds.storage
-
- self._devices = []
- self._actions = []
-
- self._ignoredDisks = []
- self.immutableDevices = []
- for disk in self.storage.ignoredDisks:
- self.addIgnoredDisk(disk)
-
- def addIgnoredDisk(self, disk):
- self._ignoredDisks.append(disk)
- lvm.lvm_cc_addFilterRejectRegexp(disk)
-
- def populate(self):
- """ Locate all storage devices. """
- # each iteration scans any devices that have appeared since the
- # previous iteration
- old_devices = []
- ignored_devices = []
- while True:
- devices = []
- new_devices = udev_get_block_devices()
-
- for new_device in new_devices:
- found = False
- for old_device in old_devices:
- if old_device['name'] == new_device['name']:
- found = True
- break
-
- if not found:
- devices.append(new_device)
-
- if len(devices) == 0:
- # nothing is changing -- we are finished building devices
- break
-
- old_devices = new_devices
- self.installer.log.info("Devices to scan: %s" % [d['name'] for d in devices])
- for dev in devices:
- self.addUdevDevice(dev)
-
- # After having the complete tree we make sure that the system
- # inconsistencies are ignored or resolved.
- #for leaf in self.leaves:
- # self._handleInconsistencies(leaf)
-
- #self.teardownAll()
- try:
- os.unlink("/etc/mdadm.conf")
- except OSError:
- pass
-
- @property
- def devices(self):
- """ Dict with device path keys and Device values. """
- devices = {}
-
- for device in self._devices:
- if device.path in devices:
- raise DeviceTreeError("duplicate paths in device tree")
-
- devices[device.path] = device
-
- return devices
-
- @property
- def filesystems(self):
- """ List of filesystems. """
- #""" Dict with mountpoint keys and filesystem values. """
- filesystems = []
- for dev in self.leaves:
- if dev.format and getattr(dev.format, 'mountpoint', None):
- filesystems.append(dev.format)
-
- return filesystems
-
- @property
- def leaves(self):
- """ List of all devices upon which no other devices exist. """
- leaves = [d for d in self._devices if d.isleaf]
- return leaves
-
- def teardownAll(self):
- """ Run teardown methods on all devices. """
- for device in self.leaves:
- try:
- device.teardown(recursive=True)
- except (DeviceError, DeviceFormatError, LVMError) as e:
- self.installer.log.info("Teardown of %s failed: %s" % (device.name, e))
-
- def _addDevice(self, newdev):
- """ Add a device to the tree.
-
- Raise ValueError if the device's identifier is already
- in the list.
- """
- if newdev.path in [d.path for d in self._devices]:
- raise ValueError("device is already in tree")
-
- # make sure this device's parent devices are in the tree already
- for parent in newdev.parents:
- if parent not in self._devices:
- raise DeviceTreeError("parent device not in tree")
-
- self._devices.append(newdev)
- self.installer.log.info("Added %s (%s) to device tree" % (newdev.name, newdev.type))
- #self.installer.log.info(" Status: %s" % newdev.status)
- #self.installer.log.info(" Format: %s" % newdev.format.type)
-
- def _removeDevice(self, dev, force=None, moddisk=True):
- """ Remove a device from the tree.
-
- Only leaves may be removed.
- """
- if dev not in self._devices:
- raise ValueError("Device '%s' not in tree" % dev.name)
-
- if not dev.isleaf and not force:
- self.installer.log.debug("%s has %d kids" % (dev.name, dev.kids))
- raise ValueError("Cannot remove non-leaf device '%s'" % dev.name)
-
- # if this is a partition we need to remove it from the parted.Disk
- if moddisk and isinstance(dev, PartitionDevice) and \
- dev.disk is not None:
- # if this partition hasn't been allocated it could not have
- # a disk attribute
- if dev.partedPartition.type == parted.PARTITION_EXTENDED and \
- len(dev.disk.partedDisk.getLogicalPartitions()) > 0:
- raise ValueError("Cannot remove extended partition %s. "
- "Logical partitions present." % dev.name)
-
- dev.disk.partedDisk.removePartition(dev.partedPartition)
-
- self._devices.remove(dev)
- self.installer.log.debug("Removed %s (%s) from device tree" % (dev.name,
- dev.type))
-
- for parent in dev.parents:
- # Will this cause issues with garbage collection?
- # Do we care about garbage collection? At all?
- parent.removeChild()
-
- def isIgnored(self, info):
- """ Return True if info is a device we should ignore.
-
- Arguments:
-
- info -- a dict representing a udev db entry
-
- TODO:
-
- - filtering of SAN/FC devices
- - filtering by driver?
-
- """
- sysfs_path = udev_device_get_sysfs_path(info)
- name = udev_device_get_name(info)
- if not sysfs_path:
- return None
-
- if name in self._ignoredDisks:
- return True
-
- for ignored in self._ignoredDisks:
- if ignored == os.path.basename(os.path.dirname(sysfs_path)):
- # this is a partition on a disk in the ignore list
- return True
-
- # Ignore partitions found on the raw disks which are part of a
- # dmraidset
- for set in self.getDevicesByType("dm-raid array"):
- for disk in set.parents:
- if disk.name == os.path.basename(os.path.dirname(sysfs_path)):
- return True
-
- # Ignore loop and ram devices, we normally already skip these in
- # udev.py: enumerate_block_devices(), but we can still end up trying
- # to add them to the tree when they are slaves of other devices, this
- # happens for example with the livecd
- if name.startswith("loop") or name.startswith("ram"):
- return True
-
- # FIXME: check for virtual devices whose slaves are on the ignore list
-
- def getDeviceByName(self, name):
- found = None
- for device in self._devices:
- if device.name == name:
- found = device
- break
- return found
-
- def getDevicesByType(self, device_type):
- # TODO: expand this to catch device format types
- return [d for d in self._devices if d.type == device_type]
-
- def getDevicesByInstance(self, device_class):
- return [d for d in self._devices if isinstance(d, device_class)]
-
- def registerAction(self, action):
- """ Register an action to be performed at a later time.
-
- Modifications to the Device instance are handled before we
- get here.
- """
- if (action.isDestroy() or action.isResize() or \
- (action.isCreate() and action.isFormat())) and \
- action.device not in self._devices:
- raise DeviceTreeError("device is not in the tree")
- elif (action.isCreate() and action.isDevice()):
- # this allows multiple create actions w/o destroy in between;
- # we will clean it up before processing actions
- #raise DeviceTreeError("device is already in the tree")
- if action.device in self._devices:
- self._removeDevice(action.device)
- for d in self._devices:
- if d.path == action.device.path:
- self._removeDevice(d)
-
- if action.isCreate() and action.isDevice():
- self._addDevice(action.device)
- elif action.isDestroy() and action.isDevice():
- self._removeDevice(action.device)
- elif action.isCreate() and action.isFormat():
- if isinstance(action.device.format, formats.fs.FS) and \
- action.device.format.mountpoint in self.filesystems:
- raise DeviceTreeError("mountpoint already in use")
-
- self.installer.log.debug("Registered action: %s" % action)
- self._actions.append(action)
-
- def addUdevDevice(self, info):
- # FIXME: this should be broken up into more discrete chunks
- name = udev_device_get_name(info)
- uuid = udev_device_get_uuid(info)
- sysfs_path = udev_device_get_sysfs_path(info)
-
- if self.isIgnored(info):
- self.installer.log.debug("Ignoring %s (%s)" % (name, sysfs_path))
- return
-
- self.installer.log.debug("Scanning %s (%s)..." % (name, sysfs_path))
- device = self.getDeviceByName(name)
-
- #
- # The first step is to either look up or create the device
- #
- if udev_device_is_dm(info):
- # try to look up the device
- if device is None and uuid:
- # try to find the device by uuid
- device = self.getDeviceByUuid(uuid)
-
- if device is None:
- device = self.addUdevDMDevice(info)
- elif udev_device_is_md(info):
- if device is None and uuid:
- # try to find the device by uuid
- device = self.getDeviceByUuid(uuid)
-
- if device is None:
- device = self.addUdevMDDevice(info)
- elif udev_device_is_cdrom(info):
- if device is None:
- device = self.addUdevOpticalDevice(info)
- elif udev_device_is_dmraid(info):
- # This is special handling to avoid the "unrecognized disklabel"
- # code since dmraid member disks won't have a disklabel. We
- # use a StorageDevice because DiskDevices need disklabels.
- # Quite lame, but it doesn't matter much since we won't use
- # the StorageDevice instances for anything.
- if device is None:
- device = StorageDevice(name,
- major=udev_device_get_major(info),
- minor=udev_device_get_minor(info),
- sysfsPath=sysfs_path, exists=True)
- self._addDevice(device)
- elif udev_device_is_disk(info):
- if device is None:
- device = self.addUdevDiskDevice(info)
- elif udev_device_is_partition(info):
- if device is None:
- device = self.addUdevPartitionDevice(info)
-
- # now handle the device's formatting
- self.handleUdevDeviceFormat(info, device)
-
- def addUdevDiskDevice(self, info):
- name = udev_device_get_name(info)
- uuid = udev_device_get_uuid(info)
- sysfs_path = udev_device_get_sysfs_path(info)
- device = None
-
- try:
- device = DiskDevice(self.installer, name,
- major=udev_device_get_major(info),
- minor=udev_device_get_minor(info),
- sysfsPath=sysfs_path,
- initlabel=False)
- except DeviceUserDeniedFormatError: #drive not initialized?
- self.addIgnoredDisk(name)
- return
-
- self._addDevice(device)
- return device
-
- def addUdevPartitionDevice(self, info):
- name = udev_device_get_name(info)
- uuid = udev_device_get_uuid(info)
- sysfs_path = udev_device_get_sysfs_path(info)
- device = None
-
- disk_name = os.path.basename(os.path.dirname(sysfs_path))
- disk = self.getDeviceByName(disk_name)
-
- if disk is None:
- # create a device instance for the disk
- path = os.path.dirname(os.path.realpath(sysfs_path))
- new_info = udev_get_block_device(path)
- if new_info:
- self.addUdevDevice(new_info)
- disk = self.getDeviceByName(disk_name)
-
- if disk is None:
- # if the current device is still not in
- # the tree, something has gone wrong
- self.installer.log.error("Failure scanning device %s" % disk_name)
- return
-
- try:
- device = PartitionDevice(self.installer, name, sysfsPath=sysfs_path,
- major=udev_device_get_major(info),
- minor=udev_device_get_minor(info),
- exists=True, parents=[disk])
- except DeviceError:
- # corner case sometime the kernel accepts a partition table
- # which gets rejected by parted, in this case we will
- # prompt to re-initialize the disk, so simply skip the
- # faulty partitions.
- return
-
- self._addDevice(device)
- return device
-
- def addUdevOpticalDevice(self, info):
- # Looks like if it has ID_INSTANCE=0:1 we can ignore it.
- device = OpticalDevice(self.installer, udev_device_get_name(info),
- major=udev_device_get_major(info),
- minor=udev_device_get_minor(info),
- sysfsPath=udev_device_get_sysfs_path(info))
- self._addDevice(device)
- return device
-
- def handleUdevDeviceFormat(self, info, device):
- #log.debug("%s" % info)
- name = udev_device_get_name(info)
- sysfs_path = udev_device_get_sysfs_path(info)
- uuid = udev_device_get_uuid(info)
- label = udev_device_get_label(info)
- format_type = udev_device_get_format(info)
-
- format = None
- if (not device) or (not format_type) or device.format.type:
- # this device has no formatting or it has already been set up
- # FIXME: this probably needs something special for disklabels
- self.installer.log.debug("no type or existing type for %s, bailing" % (name,))
- return
-
- # set up the common arguments for the format constructor
- args = [format_type]
- kwargs = {"uuid": uuid,
- "label": label,
- "device": device.path,
- "exists": True}
-
- # set up type-specific arguments for the format constructor
- if format_type == "crypto_LUKS":
- # luks/dmcrypt
- kwargs["name"] = "luks-%s" % uuid
- elif format_type == "linux_raid_member":
- # mdraid
- try:
- kwargs["mdUuid"] = udev_device_get_md_uuid(info)
- except KeyError:
- self.installer.log.debug("mdraid member %s has no md uuid" % name)
- elif format_type == "LVM2_member":
- # lvm
- try:
- kwargs["vgName"] = udev_device_get_vg_name(info)
- except KeyError as e:
- self.installer.log.debug("PV %s has no vg_name" % name)
- try:
- kwargs["vgUuid"] = udev_device_get_vg_uuid(info)
- except KeyError:
- self.installer.log.debug("PV %s has no vg_uuid" % name)
- try:
- kwargs["peStart"] = udev_device_get_pv_pe_start(info)
- except KeyError:
- self.installer.log.debug("PV %s has no pe_start" % name)
-
- try:
- self.installer.log.debug("type detected on '%s' is '%s'" % (name, format_type,))
- device.format = formats.getFormat(format_type, *args, **kwargs)
- except FSError, e:
- self.installer.log.debug("type '%s' on '%s' invalid, assuming no format - %s" %
- (format_type, name, e,))
- device.format = formats.DeviceFormat(self.installer)
- return
-
- #
- # now do any special handling required for the device's format
- #
- #if device.format.type == "luks":
- # self.handleUdevLUKSFormat(info, device)
- #elif device.format.type == "mdmember":
- # self.handleUdevMDMemberFormat(info, device)
- #elif device.format.type == "dmraidmember":
- # self.handleUdevDMRaidMemberFormat(info, device)
- #elif device.format.type == "lvmpv":
- # self.handleUdevLVMPVFormat(info, device)
-
- def handleUdevDMRaidMemberFormat(self, info, device):
- name = udev_device_get_name(info)
- sysfs_path = udev_device_get_sysfs_path(info)
- uuid = udev_device_get_uuid(info)
- major = udev_device_get_major(info)
- minor = udev_device_get_minor(info)
-
- def _all_ignored(rss):
- retval = True
- for rs in rss:
- if rs.name not in self._ignoredDisks:
- retval = False
- break
- return retval
-
- # Have we already created the DMRaidArrayDevice?
- rss = block.getRaidSetFromRelatedMem(uuid=uuid, name=name,
- major=major, minor=minor)
- if len(rss) == 0:
- # we ignore the device in the hope that all the devices
- # from this set will be ignored.
- # FIXME: Can we reformat a raid device?
- self.addIgnoredDisk(device.name)
- return
-
- # We ignore the device if all the rss are in self._ignoredDisks
- if _all_ignored(rss):
- self.addIgnoredDisk(device.name)
- return
-
- for rs in rss:
- dm_array = self.getDeviceByName(rs.name)
- if dm_array is not None:
- # We add the new device.
- dm_array._addDevice(device)
- else:
- # Activate the Raid set.
- rs.activate(mknod=True)
-
- # Create the DMRaidArray
- if self.zeroMbr:
- cb = lambda: True
- else:
- cb = lambda: questionInitializeDisk(self.intf,
- rs.name)
-
- # Create the DMRaidArray
- if not self.clearPartDisks or \
- rs.name in self.clearPartDisks:
- # if the disk contains protected partitions
- # we will not wipe the disklabel even if
- # clearpart --initlabel was specified
- initlabel = self.reinitializeDisks
- for protected in self.protectedPartitions:
- disk_name = re.sub(r'p\d+$', '', protected)
- if disk_name != protected and \
- disk_name == rs.name:
- initlabel = False
- break
-
- try:
- dm_array = DMRaidArrayDevice(rs.name,
- raidSet=rs,
- parents=[device],
- initcb=cb,
- initlabel=initlabel)
-
- self._addDevice(dm_array)
- # Use the rs's object on the device.
- # pyblock can return the memebers of a set and the
- # device has the attribute to hold it. But ATM we
- # are not really using it. Commenting this out until
- # we really need it.
- #device.format.raidmem = block.getMemFromRaidSet(dm_array,
- # major=major, minor=minor, uuid=uuid, name=name)
- except DeviceUserDeniedFormatError:
- # We should ignore the dmraid and its components
- self.addIgnoredDisk(rs.name)
- if _all_ignored(rss):
- self.addIgnoredDisk(device.name)
- rs.deactivate()
-
- def getDependentDevices(self, dep):
- """ Return a list of devices that depend on dep.
-
- The list includes both direct and indirect dependents.
- """
- dependents = []
-
- # special handling for extended partitions since the logical
- # partitions and their deps effectively depend on the extended
- logicals = []
- if isinstance(dep, PartitionDevice) and dep.partType and \
- dep.isExtended:
- # collect all of the logicals on the same disk
- for part in self.getDevicesByInstance(PartitionDevice):
- if part.partType and part.isLogical and part.disk == dep.disk:
- logicals.append(part)
+++ /dev/null
-#!/usr/bin/python
-
-class StorageError(Exception):
- pass
-
-# Device
-class DeviceError(StorageError):
- pass
-
-class DeviceCreateError(DeviceError):
- pass
-
-class DeviceDestroyError(DeviceError):
- pass
-
-class DeviceResizeError(DeviceError):
- pass
-
-class DeviceSetupError(DeviceError):
- pass
-
-class DeviceTeardownError(DeviceError):
- pass
-
-class DeviceUserDeniedFormatError(DeviceError):
- pass
-
-# DeviceFormat
-class DeviceFormatError(StorageError):
- pass
-
-class FormatCreateError(DeviceFormatError):
- pass
-
-class FormatDestroyError(DeviceFormatError):
- pass
-
-class FormatSetupError(DeviceFormatError):
- pass
-
-class FormatTeardownError(DeviceFormatError):
- pass
-
-class DMRaidMemberError(DeviceFormatError):
- pass
-
-class FSError(DeviceFormatError):
- pass
-
-class FSResizeError(FSError):
- pass
-
-class FSMigrateError(FSError):
- pass
-
-class LUKSError(DeviceFormatError):
- pass
-
-class MDMemberError(DeviceFormatError):
- pass
-
-class PhysicalVolumeError(DeviceFormatError):
- pass
-
-class SwapSpaceError(DeviceFormatError):
- pass
-
-# devicelibs
-class SwapError(StorageError):
- pass
-
-class SuspendError(SwapError):
- pass
-
-class OldSwapError(SwapError):
- pass
-
-class MDRaidError(StorageError):
- pass
-
-class DMError(StorageError):
- pass
-
-class LVMError(StorageError):
- pass
-
-class CryptoError(StorageError):
- pass
-
-# DeviceTree
-class DeviceTreeError(StorageError):
- pass
-
-# DeviceAction
-class DeviceActionError(StorageError):
- pass
-
-# partitioning
-class PartitioningError(StorageError):
- pass
-
-class PartitioningWarning(StorageError):
- pass
-
-# udev
-class UdevError(StorageError):
- pass
+++ /dev/null
-#!/usr/bin/python
-
-import os
-import copy
-
-device_formats = {}
-def register_device_format(fmt_class):
- if not issubclass(fmt_class, DeviceFormat):
- raise ValueError("Argument must be a subclass of DeviceFormat")
- device_formats[fmt_class._type] = fmt_class
-
-def getFormat(fmt_type, *args, **kwargs):
- """ Return a DeviceFormat instance based on fmt_type and args.
-
- Given a device format type and a set of constructor arguments,
- return a DeviceFormat instance.
-
- Return None if no suitable format class is found.
-
- Arguments:
-
- fmt_type -- the name of the format type (eg: 'ext3', 'swap')
-
- Keyword Arguments:
-
- The keyword arguments may vary according to the format type,
- but here is the common set:
-
- device -- path to the device on which the format resides
- uuid -- the UUID of the (preexisting) formatted device
- exists -- whether or not the format exists on the device
-
- """
- fmt_class = get_device_format_class(fmt_type)
- fmt = None
- if fmt_class:
- fmt = fmt_class(*args, **kwargs)
- try:
- className = fmt.__class__.__name__
- except AttributeError:
- className = None
- return fmt
-
-def get_device_format_class(fmt_type):
- """ Return an appropriate format class based on fmt_type. """
- if not device_formats:
- collect_device_format_classes()
-
- fmt = device_formats.get(fmt_type)
- if not fmt:
- for fmt_class in device_formats.values():
- if fmt_type and fmt_type == fmt_class._name:
- fmt = fmt_class
- break
- elif fmt_type in fmt_class._udevTypes:
- fmt = fmt_class
- break
-
- # default to no formatting, AKA "Unknown"
- if not fmt:
- fmt = DeviceFormat
- return fmt
-
-def collect_device_format_classes():
- """ Pick up all device format classes from this directory.
-
- Note: Modules must call register_device_format(FormatClass) in
- order for the format class to be picked up.
- """
- dir = os.path.dirname(__file__)
- for module_file in os.listdir(dir):
- # make sure we're not importing this module
- if module_file.endswith(".py") and module_file != __file__:
- mod_name = module_file[:-3]
- try:
- globals()[mod_name] = __import__(mod_name, globals(), locals(), [], -1)
- except ImportError, e:
- pass
-
-default_fstypes = ("ext4", "ext3", "ext2")
-default_boot_fstypes = ("ext3", "ext2")
-def get_default_filesystem_type(boot=None):
- if boot:
- fstypes = default_boot_fstypes
- else:
- fstypes = default_fstypes
-
- for fstype in fstypes:
- try:
- supported = get_device_format_class(fstype).supported
- except AttributeError:
- supported = None
-
- if supported:
- return fstype
-
- raise DeviceFormatError("None of %s is supported by your kernel" % ",".join(fstypes))
-
-class DeviceFormat(object):
- """ Generic device format. """
- _type = None
- _name = "Unknown"
- _udevTypes = []
- partedFlag = None
- _formattable = False # can be formatted
- _supported = False # is supported
- _resizable = False # can be resized
- _bootable = False # can be used as boot
- _migratable = False # can be migrated
- _maxSize = 0 # maximum size in MB
- _minSize = 0 # minimum size in MB
- _dump = False
- _check = False
-
- def __init__(self, installer, *args, **kwargs):
- """ Create a DeviceFormat instance.
-
- Keyword Arguments:
-
- device -- path to the underlying device
- uuid -- this format's UUID
- exists -- indicates whether this is an existing format
-
- """
- self.installer = installer
-
- self.device = kwargs.get("device")
- self.uuid = kwargs.get("uuid")
- self.exists = kwargs.get("exists")
- self.options = kwargs.get("options")
- self._migrate = False
-
- def __deepcopy__(self, memo):
- new = self.__class__.__new__(self.__class__)
- memo[id(self)] = new
- shallow_copy_attrs = ('installer', 'screen')
- for (attr, value) in self.__dict__.items():
- if attr in shallow_copy_attrs:
- setattr(new, attr, copy.copy(value))
- else:
- setattr(new, attr, copy.deepcopy(value, memo))
-
- return new
-
- def _setOptions(self, options):
- self._options = options
-
- def _getOptions(self):
- return self._options
-
- options = property(_getOptions, _setOptions)
-
- def _setDevice(self, devspec):
- if devspec and not devspec.startswith("/"):
- raise ValueError("device must be a fully qualified path: %s" % devspec)
- self._device = devspec
-
- def _getDevice(self):
- return self._device
-
- device = property(lambda f: f._getDevice(),
- lambda f,d: f._setDevice(d),
- doc="Full path the device this format occupies")
-
- @property
- def name(self):
- if self._name:
- name = self._name
- else:
- name = self.type
- return name
-
- @property
- def type(self):
- return self._type
-
- def probe(self):
- pass
-
- def notifyKernel(self):
- if not self.device:
- return
-
- if self.device.startswith("/dev/mapper/"):
- try:
- name = dm_node_from_name(os.path.basename(self.device))
- except Exception, e:
- self.installer.log.warning("Failed to get dm node for %s" % self.device)
- return
- elif self.device:
- name = os.path.basename(self.device)
-
- path = get_sysfs_path_by_name(name)
- try:
- notify_kernel(path, action="change")
- except Exception, e:
- self.installer.log.warning("Failed to notify kernel of change: %s" % e)
-
- def create(self, *args, **kwargs):
- # allow late specification of device path
- device = kwargs.get("device")
- if device:
- self.device = device
-
- if not os.path.exists(self.device):
- raise FormatCreateError("invalid device specification")
-
- def destroy(self, *args, **kwargs):
- # zero out the 1MB at the beginning and end of the device in the
- # hope that it will wipe any metadata from filesystems that
- # previously occupied this device
- self.installer.log.debug("Zeroing out beginning and end of %s..." % self.device)
- try:
- fd = os.open(self.device, os.O_RDWR)
- buf = '\0' * 1024 * 1024
- os.write(fd, buf)
- os.lseek(fd, -1024 * 1024, 2)
- os.write(fd, buf)
- os.close(fd)
- except OSError as e:
- if getattr(e, "errno", None) == 28: # No space left in device
- pass
- else:
- self.installer.log.error("Error zeroing out %s: %s" % (self.device, e))
- os.close(fd)
- except Exception as e:
- self.installer.log.error("Error zeroing out %s: %s" % (self.device, e))
- os.close(fd)
-
- self.exists = False
-
- def setup(self, *args, **kwargs):
- if not self.exists:
- raise FormatSetupError("format has not been created")
-
- if self.status:
- return
-
- # allow late specification of device path
- device = kwargs.get("device")
- if device:
- self.device = device
-
- if not self.device or not os.path.exists(self.device):
- raise FormatSetupError("invalid device specification")
-
- def teardown(self, *args, **kwargs):
- pass
-
- @property
- def status(self):
- return (self.exists and
- self.__class__ is not DeviceFormat and
- isinstance(self.device, str) and
- self.device and
- os.path.exists(self.device))
-
- @property
- def formattable(self):
- """ Can we create formats of this type? """
- return self._formattable
-
- @property
- def supported(self):
- """ Is this format a supported type? """
- return self._supported
-
- @property
- def resizable(self):
- """ Can formats of this type be resized? """
- return self._resizable
-
- @property
- def bootable(self):
- """ Is this format type suitable for a boot partition? """
- return self._bootable
-
- @property
- def migratable(self):
- """ Can formats of this type be migrated? """
- return self._migratable
-
- @property
- def migrate(self):
- return self._migrate
-
- @property
- def linuxNative(self):
- """ Is this format type native to linux? """
- return self._linuxNative
-
- @property
- def mountable(self):
- """ Is this something we can mount? """
- return False
-
- @property
- def dump(self):
- """ Whether or not this format will be dumped by dump(8). """
- return self._dump
-
- @property
- def check(self):
- """ Whether or not this format is checked on boot. """
- return self._check
-
- @property
- def maxSize(self):
- """ Maximum size (in MB) for this format type. """
- return self._maxSize
-
- @property
- def minSize(self):
- """ Minimum size (in MB) for this format type. """
- return self._minSize
-
-
-collect_device_format_classes()
+++ /dev/null
-#!/usr/bin/python
-
-import os
-import tempfile
-
-import isys
-
-import util
-
-from ..errors import *
-from . import DeviceFormat, register_device_format
-
-import gettext
-_ = lambda x: gettext.ldgettext("pomona", x)
-
-fs_configs = {}
-
-def get_kernel_filesystems():
- fs_list = []
- for line in open("/proc/filesystems").readlines():
- fs_list.append(line.split()[-1])
- return fs_list
-
-global kernel_filesystems
-kernel_filesystems = get_kernel_filesystems()
-
-class FS(DeviceFormat):
- """ Filesystem class. """
- _type = "Abstract Filesystem Class" # fs type name
- _mountType = None # like _type but for passing to mount
- _name = None
- _mkfs = "" # mkfs utility
- _modules = [] # kernel modules required for support
- _resizefs = "" # resize utility
- _labelfs = "" # labeling utility
- _fsck = "" # fs check utility
- _migratefs = "" # fs migration utility
- _defaultFormatOptions = [] # default options passed to mkfs
- _defaultMountOptions = ["defaults"] # default options passed to mount
- _defaultLabelOptions = []
- _defaultCheckOptions = []
- _defaultMigrateOptions = []
- _migrationTarget = None
- lostAndFoundContext = None
-
- def __init__(self, installer, *args, **kwargs):
- """ Create a FS instance.
-
- Keyword Args:
-
- device -- path to the device containing the filesystem
- mountpoint -- the filesystem's mountpoint
- label -- the filesystem label
- uuid -- the filesystem UUID
- mountopts -- mount options for the filesystem
- size -- the filesystem's size in MiB
- exists -- indicates whether this is an existing filesystem
-
- """
- if self.__class__ is FS:
- raise TypeError("FS is an abstract class.")
-
- self.installer = installer
-
- DeviceFormat.__init__(self, self.installer, *args, **kwargs)
- # TODO: fsprofiles and other ways to add format args
- self.mountpoint = kwargs.get("mountpoint")
- self.mountopts = kwargs.get("mountopts")
- self.label = kwargs.get("label")
-
- # filesystem size does not necessarily equal device size
- self._size = kwargs.get("size")
- self._mountpoint = None # the current mountpoint when mounted
- if self.exists:
- self._size = self._getExistingSize()
-
- self._targetSize = self._size
-
- if self.supported:
- self.loadModule()
-
- def _setTargetSize(self, newsize):
- """ Set a target size for this filesystem. """
- if not self.exists:
- raise FSError("filesystem has not been created")
-
- if newsize is None:
- # unset any outstanding resize request
- self._targetSize = None
- return
-
- if not self.minSize < newsize < self.maxSize:
- raise ValueError("invalid target size request")
-
- self._targetSize = newsize
-
- def _getTargetSize(self):
- """ Get this filesystem's target size. """
- return self._targetSize
-
- targetSize = property(_getTargetSize, _setTargetSize,
- doc="Target size for this filesystem")
-
- def _getSize(self):
- """ Get this filesystem's size. """
- size = self._size
- if self.resizable and self.targetSize != size:
- size = self.targetSize
- return size
-
- size = property(_getSize, doc="This filesystem's size, accounting "
- "for pending changes")
-
- def _getExistingSize(self):
- """ Determine the size of this filesystem. Filesystem must
- exist.
- """
- size = 0
-
- if self.mountable:
- origMountPoint = self._mountpoint
-
- tmppath = tempfile.mkdtemp(prefix='getsize-', dir='/tmp')
- self.mount(mountpoint=tmppath, options="ro")
- buf = os.statvfs(tmppath)
- self.unmount()
- os.rmdir(tmppath)
-
- self._mountpoint = origMountPoint
-
- size = (buf.f_frsize * buf.f_blocks) / 1024.0 / 1024.0
-
- return size
-
- @property
- def currentSize(self):
- """ The filesystem's current actual size. """
- size = 0
- if self.exists:
- size = self._size
- return float(size)
-
- def _getFormatOptions(self, options=None):
- argv = []
- if options and isinstance(options, list):
- argv.extend(options)
- argv.extend(self.defaultFormatOptions)
- argv.append(self.device)
- return argv
-
- def doFormat(self, *args, **kwargs):
- """ Create the filesystem.
-
- Arguments:
-
- None
-
- Keyword Arguments:
-
- intf -- InstallInterface instance
- options -- list of options to pass to mkfs
-
- """
- intf = kwargs.get("intf")
- options = kwargs.get("options")
-
- if self.exists:
- raise FormatCreateError("filesystem already exists", self.device)
-
- if not self.formattable:
- return
-
- if not self.mkfsProg:
- return
-
- if self.exists:
- return
-
- if not os.path.exists(self.device):
- raise FormatCreateError("device does not exist", self.device)
-
- argv = self._getFormatOptions(options=options)
-
- self.installer.window = None
- self.installer.window = self.installer.intf.progressWindow(_("Formatting"),
- _("Creating filesystem on %s...") % (self.device,),
- 100, pulse = True)
-
- try:
- rc = util.execWithPulseProgress(self.mkfsProg,
- argv,
- stdout="/dev/tty5",
- stderr="/dev/tty5",
- progress=w)
- except Exception as e:
- raise FormatCreateError(e, self.device)
- finally:
- if self.installer.window:
- self.installer.window.pop()
-
- if rc:
- raise FormatCreateError("format failed: %s" % rc, self.device)
-
- self.exists = True
- self.notifyKernel()
-
- def doMigrate(self, intf=None):
- if not self.exists:
- raise FSError("filesystem has not been created")
-
- if not self.migratable or not self.migrate:
- return
-
- if not os.path.exists(self.device):
- raise FSError("device does not exist")
-
- # if journal already exists skip
- if isys.ext2HasJournal(self.device):
- self.installer.log.info("Skipping migration of %s, has a journal already." % self.device)
- return
-
- argv = self._defaultMigrateOptions[:]
- argv.append(self.device)
- try:
- rc = util.execWithRedirect(self.migratefsProg,
- argv,
- stdout = "/dev/tty5",
- stderr = "/dev/tty5",
- searchPath = 1)
- except Exception as e:
- raise FSMigrateError("filesystem migration failed: %s" % e, self.device)
-
- if rc:
- raise FSMigrateError("filesystem migration failed: %s" % rc, self.device)
-
- # the other option is to actually replace this instance with an
- # instance of the new filesystem type.
- self._type = self.migrationTarget
-
- @property
- def resizeArgs(self):
- argv = [self.device, "%d" % (self.targetSize,)]
- return argv
-
- def doResize(self, *args, **kwargs):
- """ Resize this filesystem to new size @newsize.
-
- Arguments:
-
- None
-
- Keyword Arguments:
-
- intf -- InstallInterface instance
-
- """
- intf = kwargs.get("intf")
-
- if not self.exists:
- raise FSResizeError("filesystem does not exist", self.device)
-
- if not self.resizable:
- raise FSResizeError("filesystem not resizable", self.device)
-
- if self.targetSize == self.currentSize:
- return
-
- if not self.resizefsProg:
- return
-
- if not os.path.exists(self.device):
- raise FSResizeError("device does not exist", self.device)
-
- self.doCheck(intf=intf)
-
- w = None
- if intf:
- w = intf.progressWindow(_("Resizing"),
- _("Resizing filesystem on %s...")
- % (self.device,),
- 100, pulse = True)
-
- try:
- rc = util.execWithPulseProgress(self.resizefsProg,
- self.resizeArgs,
- stdout="/dev/tty5",
- stderr="/dev/tty5",
- progress=w)
- except Exception as e:
- raise FSResizeError(e, self.device)
- finally:
- if w:
- w.pop()
-
- if rc:
- raise FSResizeError("resize failed: %s" % rc, self.device)
-
- # XXX must be a smarter way to do this
- self._size = self.targetSize
- self.notifyKernel()
-
- def _getCheckArgs(self):
- argv = []
- argv.extend(self.defaultCheckOptions)
- argv.append(self.device)
- return argv
-
- def doCheck(self, intf=None):
- if not self.exists:
- raise FSError("filesystem has not been created")
-
- if not self.fsckProg:
- return
-
- if not os.path.exists(self.device):
- raise FSError("device does not exist")
-
- w = None
- if intf:
- w = intf.progressWindow(_("Checking"),
- _("Checking filesystem on %s...")
- % (self.device),
- 100, pulse = True)
-
- try:
- rc = util.execWithPulseProgress(self.fsckProg,
- self._getCheckArgs(),
- stdout="/dev/tty5",
- stderr="/dev/tty5",
- progress = w)
- except Exception as e:
- raise FSError("filesystem check failed: %s" % e)
- finally:
- if w:
- w.pop()
-
- if rc >= 4:
- raise FSError("filesystem check failed: %s" % rc)
-
- def loadModule(self):
- """Load whatever kernel module is required to support this filesystem."""
- global kernel_filesystems
-
- if not self._modules or self.mountType in kernel_filesystems:
- return
-
- for module in self._modules:
- try:
- rc = util.execWithRedirect("modprobe", [module],
- stdout="/dev/tty5", stderr="/dev/tty5",
- searchPath=1)
- except Exception as e:
- self.installer.log.error("Could not load kernel module %s: %s" % (module, e))
- self._supported = False
- return
-
- if rc:
- self.installer.log.error("Could not load kernel module %s" % module)
- self._supported = False
- return
-
- # If we successfully loaded a kernel module, for this filesystem, we
- # also need to update the list of supported filesystems.
- kernel_filesystems = get_kernel_filesystems()
-
- def mount(self, *args, **kwargs):
- """ Mount this filesystem.
-
- Arguments:
-
- None
-
- Keyword Arguments:
-
- options -- mount options (overrides all other option strings)
- chroot -- prefix to apply to mountpoint
- mountpoint -- mountpoint (overrides self.mountpoint)
- """
- options = kwargs.get("options", "")
- chroot = kwargs.get("chroot", "/")
- mountpoint = kwargs.get("mountpoint")
-
- if not self.exists:
- raise FSError("filesystem has not been created")
-
- if not mountpoint:
- mountpoint = self.mountpoint
-
- if not mountpoint:
- raise FSError("no mountpoint given")
-
- if self.status:
- return
-
- if not isinstance(self, NoDevFS) and not os.path.exists(self.device):
- raise FSError("device %s does not exist" % self.device)
-
- # XXX os.path.join is FUBAR:
- #
- # os.path.join("/mnt/foo", "/") -> "/"
- #
- #mountpoint = os.path.join(chroot, mountpoint)
- mountpoint = os.path.normpath("%s/%s" % (chroot, mountpoint))
- util.mkdirChain(mountpoint)
-
- # passed in options override default options
- if not options or not isinstance(options, str):
- options = self.options
-
- try:
- rc = isys.mount(self.device, mountpoint,
- fstype=self.mountType,
- options=options,
- bindMount=isinstance(self, BindFS))
- except Exception as e:
- raise FSError("mount failed: %s" % e)
-
- if rc:
- raise FSError("mount failed: %s" % rc)
-
- self._mountpoint = mountpoint
-
- def unmount(self):
- """ Unmount this filesystem. """
- if not self.exists:
- raise FSError("filesystem has not been created")
-
- if not self._mountpoint:
- # not mounted
- return
-
- if not os.path.exists(self._mountpoint):
- raise FSError("mountpoint does not exist")
-
- rc = isys.umount(self._mountpoint, removeDir = False)
- if rc:
- raise FSError("umount failed")
-
- self._mountpoint = None
-
- def _getLabelArgs(self, label):
- argv = []
- argv.extend(self.defaultLabelOptions)
- argv.extend([self.device, label])
- return argv
-
- def writeLabel(self, label):
- """ Create a label for this filesystem. """
- if not self.exists:
- raise FSError("filesystem has not been created")
-
- if not self.labelfsProg:
- return
-
- if not os.path.exists(self.device):
- raise FSError("device does not exist")
-
- argv = self._getLabelArgs(label)
- rc = util.execWithRedirect(self.labelfsProg,
- argv,
- stderr="/dev/tty5",
- searchPath=1)
- if rc:
- raise FSError("label failed")
-
- self.label = label
- self.notifyKernel()
-
- @property
- def isDirty(self):
- return False
-
- @property
- def mkfsProg(self):
- """ Program used to create filesystems of this type. """
- return self._mkfs
-
- @property
- def fsckProg(self):
- """ Program used to check filesystems of this type. """
- return self._fsck
-
- @property
- def resizefsProg(self):
- """ Program used to resize filesystems of this type. """
- return self._resizefs
-
- @property
- def labelfsProg(self):
- """ Program used to manage labels for this filesystem type. """
- return self._labelfs
-
- @property
- def migratefsProg(self):
- """ Program used to migrate filesystems of this type. """
- return self._migratefs
-
- @property
- def migrationTarget(self):
- return self._migrationTarget
-
- @property
- def utilsAvailable(self):
- # we aren't checking for fsck because we shouldn't need it
- for prog in [self.mkfsProg, self.resizefsProg, self.labelfsProg]:
- if not prog:
- continue
-
- if not filter(lambda d: os.access("%s/%s" % (d, prog), os.X_OK),
- os.environ["PATH"].split(":")):
- return False
-
- return True
-
- @property
- def supported(self):
- return self._supported and self.utilsAvailable
-
- @property
- def mountable(self):
- return (self.mountType in kernel_filesystems) or \
- (os.access("/sbin/mount.%s" % (self.mountType,), os.X_OK))
-
- @property
- def defaultFormatOptions(self):
- """ Default options passed to mkfs for this filesystem type. """
- # return a copy to prevent modification
- return self._defaultFormatOptions[:]
-
- @property
- def defaultMountOptions(self):
- """ Default options passed to mount for this filesystem type. """
- # return a copy to prevent modification
- return self._defaultMountOptions[:]
-
- @property
- def defaultLabelOptions(self):
- """ Default options passed to labeler for this filesystem type. """
- # return a copy to prevent modification
- return self._defaultLabelOptions[:]
-
- @property
- def defaultCheckOptions(self):
- """ Default options passed to checker for this filesystem type. """
- # return a copy to prevent modification
- return self._defaultCheckOptions[:]
-
- def _getOptions(self):
- options = ",".join(self.defaultMountOptions)
- if self.mountopts:
- # XXX should we clobber or append?
- options = self.mountopts
- return options
-
- def _setOptions(self, options):
- self.mountopts = options
-
- options = property(_getOptions, _setOptions)
-
- @property
- def migratable(self):
- """ Can filesystems of this type be migrated? """
- return bool(self._migratable and self.migratefsProg and
- filter(lambda d: os.access("%s/%s"
- % (d, self.migratefsProg,),
- os.X_OK),
- os.environ["PATH"].split(":")) and
- self.migrationTarget)
-
- def _setMigrate(self, migrate):
- if not migrate:
- self._migrate = migrate
- return
-
- if self.migratable and self.exists:
- self._migrate = migrate
- else:
- raise ValueError("Cannot set migrate on non-migratable filesystem")
-
- migrate = property(lambda f: f._migrate, lambda f,m: f._setMigrate(m))
-
- @property
- def type(self):
- _type = self._type
- if self.migrate:
- _type = self.migrationTarget
-
- return _type
-
- @property
- def mountType(self):
- if not self._mountType:
- self._mountType = self._type
-
- return self._mountType
-
- # These methods just wrap filesystem-specific methods in more
- # generically named methods so filesystems and formatted devices
- # like swap and LVM physical volumes can have a common API.
- def create(self, *args, **kwargs):
- if self.exists:
- raise FSError("Filesystem already exists")
-
- DeviceFormat.create(self, *args, **kwargs)
-
- return self.doFormat(*args, **kwargs)
-
- def setup(self, *args, **kwargs):
- """ Mount the filesystem.
-
- THe filesystem will be mounted at the directory indicated by
- self.mountpoint.
- """
- return self.mount(**kwargs)
-
- def teardown(self, *args, **kwargs):
- return self.unmount(*args, **kwargs)
-
- @property
- def status(self):
- # FIXME check /proc/mounts or similar
- if not self.exists:
- return False
- return self._mountpoint is not None
-
-
-class Ext2FS(FS):
- """ ext2 filesystem. """
- _type = "ext2"
- _mkfs = "mke2fs"
- _modules = ["ext2"]
- _resizefs = "resize2fs"
- _labelfs = "e2label"
- _fsck = "e2fsck"
- _formattable = True
- _supported = True
- _resizable = True
- _bootable = True
- _linuxNative = True
- _maxSize = 8 * 1024 * 1024
- _minSize = 0
- _defaultFormatOptions = []
- _defaultMountOptions = ["defaults"]
- _defaultCheckOptions = ["-f", "-p", "-C", "0"]
- _dump = True
- _check = True
- _migratable = True
- _migrationTarget = "ext3"
- _migratefs = "tune2fs"
- _defaultMigrateOptions = ["-j"]
-
- @property
- def minSize(self):
- """ Minimum size for this filesystem in MB. """
- size = self._minSize
- if self.exists and os.path.exists(self.device):
- buf = util.execWithCapture(self.resizefsProg,
- ["-P", self.device],
- stderr="/dev/tty5")
- size = None
- for line in buf.splitlines():
- if "minimum size of the filesystem:" not in line:
- continue
-
- (text, sep, minSize) = line.partition(": ")
-
- size = int(minSize) / 1024.0
-
- if size is None:
- self.installer.log.warning("failed to get minimum size for %s filesystem "
- "on %s" % (self.mountType, self.device))
- size = self._minSize
-
- return size
-
- @property
- def isDirty(self):
- return isys.ext2IsDirty(self.device)
-
- @property
- def resizeArgs(self):
- argv = ["-p", self.device, "%dM" % (self.targetSize,)]
- return argv
-
-register_device_format(Ext2FS)
-
-
-class Ext3FS(Ext2FS):
- """ ext3 filesystem. """
- _type = "ext3"
- _defaultFormatOptions = ["-t", "ext3"]
- _migrationTarget = "ext4"
- _modules = ["ext3"]
- _defaultMigrateOptions = ["-O", "extents"]
-
- @property
- def migratable(self):
- """ Can filesystems of this type be migrated? """
- return (flags.cmdline.has_key("ext4migrate") and
- Ext2FS.migratable)
-
-register_device_format(Ext3FS)
-
-
-class Ext4FS(Ext3FS):
- """ ext4 filesystem. """
- _type = "ext4"
- _bootable = False
- _defaultFormatOptions = ["-t", "ext4"]
- _migratable = False
- _modules = ["ext4"]
-
-register_device_format(Ext4FS)
-
-
-class FATFS(FS):
- """ FAT filesystem. """
- _type = "vfat"
- _mkfs = "mkdosfs"
- _modules = ["vfat"]
- _labelfs = "dosfslabel"
- _fsck = "dosfsck"
- _formattable = True
- _maxSize = 1024 * 1024
- _defaultMountOptions = ["umask=0077", "shortname=winnt"]
-
-register_device_format(FATFS)
-
-
-class BTRFS(FS):
- """ btrfs filesystem """
- _type = "btrfs"
- _mkfs = "mkfs.btrfs"
- _modules = ["btrfs"]
- _resizefs = "btrfsctl"
- _formattable = True
- _linuxNative = True
- _bootable = False
- _maxLabelChars = 256
- _supported = True
- _dump = True
- _check = True
- _maxSize = 16 * 1024 * 1024
-
- def _getFormatOptions(self, options=None):
- argv = []
- if options and isinstance(options, list):
- argv.extend(options)
- argv.extend(self.defaultFormatOptions)
- if self.label:
- argv.extend(["-L", self.label])
- argv.append(self.device)
- return argv
-
- @property
- def resizeArgs(self):
- argv = ["-r", "%dm" % (self.targetSize,), self.device]
- return argv
-
-register_device_format(BTRFS)
-
-class XFS(FS):
- """ XFS filesystem """
- _type = "xfs"
- _mkfs = "mkfs.xfs"
- _modules = ["xfs"]
- _labelfs = "xfs_admin"
- _defaultFormatOptions = ["-f"]
- _defaultLabelOptions = ["-L"]
- _maxLabelChars = 16
- _maxSize = 16 * 1024 * 1024
- _formattable = True
- _linuxNative = True
- _supported = True
- _dump = True
- _check = True
-
-register_device_format(XFS)
-
-class NTFS(FS):
- """ ntfs filesystem. """
- _type = "ntfs"
- _resizefs = "ntfsresize"
- _fsck = "ntfsresize"
- _resizable = True
- _minSize = 1
- _maxSize = 16 * 1024 * 1024
- _defaultMountOptions = ["defaults"]
- _defaultCheckOptions = ["-c"]
-
- @property
- def minSize(self):
- """ The minimum filesystem size in megabytes. """
- size = self._minSize
- if self.exists and os.path.exists(self.device):
- minSize = None
- buf = util.execWithCapture(self.resizefsProg,
- ["-m", self.device],
- stderr = "/dev/tty5")
- for l in buf.split("\n"):
- if not l.startswith("Minsize"):
- continue
- try:
- min = l.split(":")[1].strip()
- minSize = int(min) + 250
- except Exception, e:
- minSize = None
- self.installer.log.warning("Unable to parse output for minimum size on %s: %s" %(self.device, e))
-
- if minSize is None:
- self.installer.log.warning("Unable to discover minimum size of filesystem "
- "on %s" %(self.device,))
- else:
- size = minSize
-
- return size
-
- @property
- def resizeArgs(self):
- # You must supply at least two '-f' options to ntfsresize or
- # the proceed question will be presented to you.
- argv = ["-ff", "-s", "%dM" % (self.targetSize,), self.device]
- return argv
-
-register_device_format(NTFS)
-
-
-# if this isn't going to be mountable it might as well not be here
-class NFS(FS):
- """ NFS filesystem. """
- _type = "nfs"
- _modules = ["nfs"]
-
- def _deviceCheck(self, devspec):
- if devspec is not None and ":" not in devspec:
- raise ValueError("device must be of the form <host>:<path>")
-
- @property
- def mountable(self):
- return False
-
- def _setDevice(self, devspec):
- self._deviceCheck(devspec)
- self._device = devspec
-
- def _getDevice(self):
- return self._device
-
- device = property(lambda f: f._getDevice(),
- lambda f,d: f._setDevice(d),
- doc="Full path the device this format occupies")
-
-register_device_format(NFS)
-
-
-class NFSv4(NFS):
- """ NFSv4 filesystem. """
- _type = "nfs4"
- _modules = ["nfs4"]
-
-register_device_format(NFSv4)
-
-
-class Iso9660FS(FS):
- """ ISO9660 filesystem. """
- _type = "iso9660"
- _formattable = False
- _supported = True
- _resizable = False
- _bootable = False
- _linuxNative = False
- _dump = False
- _check = False
- _migratable = False
- _defaultMountOptions = ["ro"]
-
-register_device_format(Iso9660FS)
-
-
-class NoDevFS(FS):
- """ nodev filesystem base class """
- _type = "nodev"
-
- def __init__(self, *args, **kwargs):
- FS.__init__(self, *args, **kwargs)
- self.exists = True
- self.device = self.type
-
- def _setDevice(self, devspec):
- self._device = devspec
-
-register_device_format(NoDevFS)
-
-
-class DevPtsFS(NoDevFS):
- """ devpts filesystem. """
- _type = "devpts"
- _defaultMountOptions = ["gid=5", "mode=620"]
-
-register_device_format(DevPtsFS)
-
-
-# these don't really need to be here
-class ProcFS(NoDevFS):
- _type = "proc"
-
-register_device_format(ProcFS)
-
-
-class SysFS(NoDevFS):
- _type = "sysfs"
-
-register_device_format(SysFS)
-
-
-class TmpFS(NoDevFS):
- _type = "tmpfs"
-
-register_device_format(TmpFS)
-
-
-class BindFS(FS):
- _type = "bind"
-
- @property
- def mountable(self):
- return True
-
-register_device_format(BindFS)
+++ /dev/null
-#!/usr/bin/python
-
-import os
-
-from ..errors import *
-#from ..devicelibs import crypto
-from . import DeviceFormat, register_device_format
-
-import gettext
-_ = lambda x: gettext.ldgettext("pomona", x)
-
-class LUKS(DeviceFormat):
- """ A LUKS device. """
- _type = "luks"
- _name = "LUKS"
- _udevTypes = ["crypto_LUKS"]
- _formattable = True # can be formatted
- _supported = False # is supported
- _linuxNative = True # for clearpart
-
- def __init__(self, *args, **kwargs):
- """ Create a LUKS instance.
-
- Keyword Arguments:
-
- device -- the path to the underlying device
- name -- the name of the mapped device
- uuid -- this device's UUID
- passphrase -- device passphrase (string)
- key_file -- path to a file containing a key (string)
- cipher -- cipher mode string
- key_size -- key size in bits
- exists -- indicates whether this is an existing format
- """
- DeviceFormat.__init__(self, *args, **kwargs)
- self.cipher = kwargs.get("cipher")
- self.key_size = kwargs.get("key_size")
- self.mapName = kwargs.get("name")
-
- if not self.exists and not self.cipher:
- self.cipher = "aes-xts-plain"
- if not self.key_size:
- # default to the max (512 bits) for aes-xts
- self.key_size = 512
-
- # FIXME: these should both be lists, but managing them will be a pain
- self.__passphrase = kwargs.get("passphrase")
- self._key_file = kwargs.get("key_file")
-
- if not self.mapName and self.exists and self.uuid:
- self.mapName = "luks-%s" % self.uuid
- elif not self.mapName and self.device:
- self.mapName = "luks-%s" % os.path.basename(self.device)
-
- def _setPassphrase(self, passphrase):
- """ Set the passphrase used to access this device. """
- self.__passphrase = passphrase
-
- passphrase = property(fset=_setPassphrase)
-
- @property
- def hasKey(self):
- return (self.__passphrase or
- (self._key_file and os.access(self._key_file, os.R_OK)))
-
- @property
- def configured(self):
- """ To be ready we need a key or passphrase and a map name. """
- return self.hasKey and self.mapName
-
- @property
- def status(self):
- if not self.exists or not self.mapName:
- return False
- return os.path.exists("/dev/mapper/%s" % self.mapName)
-
- def probe(self):
- """ Probe for any missing information about this format.
-
- cipher mode, key size
- """
- raise NotImplementedError("Probe method not defined for LUKS")
-
- def setup(self, *args, **kwargs):
- """ Open, or set up, the format. """
- if not self.configured:
- raise LUKSError("luks device not configured")
-
- if self.status:
- return
-
- DeviceFormat.setup(self, *args, **kwargs)
- crypto.luks_open(self.device, self.mapName,
- passphrase=self.__passphrase,
- key_file=self._key_file)
-
- def teardown(self, *args, **kwargs):
- """ Close, or tear down, the format. """
- if not self.exists:
- raise LUKSError("format has not been created")
-
- if self.status:
- log.debug("unmapping %s" % self.mapName)
- crypto.luks_close(self.mapName)
-
- def create(self, *args, **kwargs):
- """ Create the format. """
- if not self.hasKey:
- raise LUKSError("luks device has no key/passphrase")
-
- DeviceFormat.create(self, *args, **kwargs)
- crypto.luks_format(self.device,
- passphrase=self.__passphrase,
- key_file=self._key_file,
- cipher=self.cipher,
- key_size=self.key_size)
-
- self.uuid = crypto.luks_uuid(self.device)
- self.exists = True
- self.mapName = "luks-%s" % self.uuid
- self.notifyKernel()
-
- def destroy(self, *args, **kwargs):
- """ Create the format. """
- self.teardown()
- DeviceFormat.destroy(self, *args, **kwargs)
-
- @property
- def keyFile(self):
- """ Path to key file to be used in /etc/crypttab """
- return self._key_file
-
- def addKeyFromFile(self, keyfile):
- """ Add a new key from a file.
-
- Add the contents of the specified key file to an available key
- slot in the LUKS header.
- """
- if not self.exists:
- raise LUKSError("Format has not been created")
-
- crypto.luks_add_key(self.device,
- passphrase=self.__passphrase,
- key_file=self._key_file,
- new_key_file=keyfile)
-
- def addPassphrase(self, passphrase):
- """ Add a new passphrase.
-
- Add the specified passphrase to an available key slot in the
- LUKS header.
- """
- if not self.exists:
- raise LUKSError("Format has not been created")
-
- crypto.luks_add_key(self.device,
- passphrase=self.__passphrase,
- key_file=self._key_file,
- new_passphrase=passphrase)
-
- def removeKeyFromFile(self, keyfile):
- """ Remove a key contained in a file.
-
- Remove key contained in the specified key file from the LUKS
- header.
- """
- if not self.exists:
- raise LUKSError("Format has not been created")
-
- crypto.luks_remove_key(self.device,
- passphrase=self.__passphrase,
- key_file=self._key_file,
- del_key_file=keyfile)
-
-
- def removePassphrase(self, passphrase):
- """ Remove the specified passphrase from the LUKS header. """
- if not self.exists:
- raise LUKSError("Format has not been created")
-
- crypto.luks_remove_key(self.device,
- passphrase=self.__passphrase,
- key_file=self._key_file,
- del_passphrase=passphrase)
-
-
-register_device_format(LUKS)
+++ /dev/null
-#!/usr/bin/python
-
-from parted import PARTITION_LVM
-
-from . import DeviceFormat, register_device_format
-from ..errors import *
-from ..devicelibs import lvm
-
-class LVMPhysicalVolume(DeviceFormat):
- """ An LVM physical volume. """
- _type = "lvmpv"
- _name = "physical volume (LVM)"
- _udevTypes = ["LVM2_member"]
- partedFlag = PARTITION_LVM
- _formattable = True # can be formatted
- _supported = True # is supported
- _linuxNative = True # for clearpart
-
- def __init__(self, *args, **kwargs):
- """ Create an LVMPhysicalVolume instance.
-
- Keyword Arguments:
-
- device -- path to the underlying device
- uuid -- this PV's uuid (not the VG uuid)
- vgName -- the name of the VG this PV belongs to
- vgUuid -- the UUID of the VG this PV belongs to
- peStart -- offset of first physical extent
- exists -- indicates whether this is an existing format
-
- """
- DeviceFormat.__init__(self, *args, **kwargs)
- self.vgName = kwargs.get("vgName")
- self.vgUuid = kwargs.get("vgUuid")
- # liblvm may be able to tell us this at some point, even
- # for not-yet-created devices
- self.peStart = kwargs.get("peStart", 0.1875) # in MB
-
- def probe(self):
- """ Probe for any missing information about this device. """
- if not self.exists:
- raise PhysicalVolumeError("format has not been created")
-
- #info = lvm.pvinfo(self.device)
- #self.vgName = info['vg_name']
- #self.vgUuid = info['vg_uuid']
-
- def create(self, *args, **kwargs):
- """ Create the format. """
- DeviceFormat.create(self, *args, **kwargs)
- # Consider use of -Z|--zero
- # -f|--force or -y|--yes may be required
-
- # lvm has issues with persistence of metadata, so here comes the
- # hammer...
- DeviceFormat.destroy(self, *args, **kwargs)
-
- lvm.pvcreate(self.device)
- self.exists = True
- self.notifyKernel()
-
- def destroy(self, *args, **kwargs):
- """ Destroy the format. """
- if not self.exists:
- raise PhysicalVolumeError("format has not been created")
-
- if self.status:
- raise PhysicalVolumeError("device is active")
-
- # FIXME: verify path exists?
- try:
- lvm.pvremove(self.device)
- except LVMError:
- DeviceFormat.destroy(self, *args, **kwargs)
-
- self.exists = False
- self.notifyKernel()
-
- @property
- def status(self):
- # XXX hack
- return (self.exists and self.vgName and
- os.path.isdir("/dev/mapper/%s" % self.vgName))
-
-register_device_format(LVMPhysicalVolume)
+++ /dev/null
-#!/usr/bin/python
-
-from parted import PARTITION_SWAP
-
-from . import DeviceFormat, register_device_format
-from ..devicelibs import swap
-
-class SwapSpace(DeviceFormat):
- """ Swap space """
- _type = "swap"
- _name = None
- _udevTypes = ["swap"]
- partedFlag = PARTITION_SWAP
- _formattable = True # can be formatted
- _supported = True # is supported
- _linuxNative = True # for clearpart
-
- def __init__(self, installer, *args, **kwargs):
- """ Create a SwapSpace instance.
-
- Keyword Arguments:
-
- device -- path to the underlying device
- uuid -- this swap space's uuid
- label -- this swap space's label
- priority -- this swap space's priority
- exists -- indicates whether this is an existing format
-
- """
- self.installer = installer
- DeviceFormat.__init__(self, self.installer, *args, **kwargs)
-
- self.priority = kwargs.get("priority")
- self.label = kwargs.get("label")
-
- def _setPriority(self, priority):
- if priority is None:
- self._priority = None
- return
-
- if not isinstance(priority, int) or not 0 <= priority <= 32767:
- raise ValueError("swap priority must be an integer between 0 and 32767")
-
- self._priority = priority
-
- def _getPriority(self):
- return self._priority
-
- priority = property(_getPriority, _setPriority,
- doc="The priority of the swap device")
-
- def _getOptions(self):
- opts = ""
- if self.priority is not None:
- opts += "pri=%d" % self.priority
-
- return opts
-
- def _setOptions(self, opts):
- if not opts:
- self.priority = None
- return
-
- for option in opts.split(","):
- (opt, equals, arg) = option.partition("=")
- if equals and opt == "pri":
- try:
- self.priority = int(arg)
- except ValueError:
- self.installer.log.info("invalid value for swap priority: %s" % arg)
-
- options = property(_getOptions, _setOptions,
- doc="The swap device's fstab options string")
-
- @property
- def status(self):
- """ Device status. """
- return self.exists and swap.swapstatus(self.device)
-
- def setup(self, *args, **kwargs):
- """ Open, or set up, a device. """
- if not self.exists:
- raise SwapSpaceError("format has not been created")
-
- if self.status:
- return
-
- DeviceFormat.setup(self, *args, **kwargs)
- swap.swapon(self.device, priority=self.priority)
-
- def teardown(self, *args, **kwargs):
- """ Close, or tear down, a device. """
- if not self.exists:
- raise SwapSpaceError("format has not been created")
-
- if self.status:
- swap.swapoff(self.device)
-
- def create(self, *args, **kwargs):
- """ Create the device. """
- if self.exists:
- raise SwapSpaceError("format already exists")
-
- if self.status:
- raise SwapSpaceError("device exists and is active")
-
- DeviceFormat.create(self, *args, **kwargs)
- swap.mkswap(self.device, label=self.label)
- self.exists = True
-
-
-register_device_format(SwapSpace)
+++ /dev/null
-#!/usr/bin/python
-
-import os
-import parted
-
-from constants import *
-from errors import *
-
-import gettext
-_ = lambda x: gettext.ldgettext("pomona", x)
-
-def doAutoPartition(installer):
- if installer.dispatch.dir == DISPATCH_BACK:
- installer.ds.storage.reset()
- return
-
- disks = []
- devs = []
-
- if installer.ds.storage.doAutoPart:
- clearPartitions(installer)
- (disks, devs) = _createFreeSpacePartitions(installer)
-
- if disks == []:
- installer.intf.messageWindow(_("Error Partitioning"),
- _("Could not find enough free space "
- "for automatic partitioning, please "
- "use another partitioning method."))
- return DISPATCH_BACK
-
- _schedulePartitions(installer, disks)
-
- # run the autopart function to allocate and grow partitions
- try:
- doPartitioning(installer)
-
- if installer.ds.storage.doAutoPart:
- _scheduleLVs(installer, devs)
-
- # grow LVs
- growLVM(installer)
- except PartitioningWarning as msg:
- installer.intf.messageWindow(_("Warnings During Automatic Partitioning"),
- _("Following warnings occurred during automatic "
- "partitioning:\n\n%s") % (msg,),)
- log.warning(msg)
- except PartitioningError as msg:
- # restore drives to original state
- installer.ds.storage.reset()
- #installer.dispatch.skipStep("partition", skip = 0)
- installer.intf.messageWindow(_("Error Partitioning"),
- _("Could not allocate requested partitions: \n\n"
- "%s.%s") % (msg, extra))
- return
-
- # now do a full check of the requests
- (errors, warnings) = installer.ds.storage.sanityCheck()
- if warnings:
- for warning in warnings:
- installer.log.warning(warning)
- if errors:
- errortxt = "\n".join(errors)
- installer.intf.messageWindow(_("Automatic Partitioning Errors"),
- _("The following errors occurred with your "
- "partitioning:\n\n%s\n\n"
- "This can happen if there is not enough "
- "space on your hard drive(s) for the "
- "installation.\n\n"
- "Press 'OK' to choose a different partitioning option.")
- % (errortxt,),)
-
- installer.ds.storage.reset()
- #XXX return DISPATCH_BACK
- return INSTALL_OK
-
-def doPartitioning(installer):
- """ Allocate and grow partitions.
-
- When this function returns without error, all PartitionDevice
- instances must have their parents set to the disk they are
- allocated on, and their partedPartition attribute set to the
- appropriate parted.Partition instance from their containing
- disk. All req_xxxx attributes must be unchanged.
-
- Arguments:
-
- storage - Main anaconda Storage instance
-
- Keyword arguments:
-
- exclusiveDisks -- list of names of disks to use
-
- """
- storage = installer.ds.storage
- disks = storage.disks
-
- exclusiveDisks = storage.clearDisks
- if exclusiveDisks:
- disks = [d for d in disks if d.name in exclusiveDisks]
-
- for disk in disks:
- disk.setup()
-
- partitions = storage.partitions
- for part in partitions:
- part.req_bootable = False
- if not part.exists:
- # start over with flexible-size requests
- part.req_size = part.req_base_size
-
- # FIXME: isn't there a better place for this to happen?
- #try:
- # bootDev = anaconda.platform.bootDevice()
- #except DeviceError:
- # bootDev = None
-
- #if bootDev:
- # bootDev.req_bootable = True
-
- # FIXME: make sure non-existent partitions have empty parents list
- allocatePartitions(installer, disks, partitions)
- growPartitions(installer, disks, partitions)
- # The number and thus the name of partitions may have changed now,
- # allocatePartitions() takes care of this for new partitions, but not
- # for pre-existing ones, so we update the name of all partitions here
- for part in partitions:
- part.updateName()
-
- # XXX hack -- if we created any extended partitions we need to add
- # them to the tree now
- for disk in disks:
- extended = disk.partedDisk.getExtendedPartition()
- if not extended:
- continue
-
- extendedName = devicePathToName(extended.getDeviceNodeName())
- device = storage.devicetree.getDeviceByName(extendedName)
- if device:
- if not device.exists:
- # created by us, update partedPartition
- device.partedPartition = extended
- continue
-
- # This is a little odd because normally instantiating a partition
- # that does not exist means leaving self.parents empty and instead
- # populating self.req_disks. In this case, we need to skip past
- # that since this partition is already defined.
- device = PartitionDevice(extendedName, parents=disk)
- device.parents = [disk]
- device.partedPartition = extended
- storage.createDevice(device)
-
-def clearPartitions(installer):
- """ Clear partitions and dependent devices from disks.
-
- Arguments:
-
- storage -- a storage.Storage instance
-
- Keyword arguments:
-
- None
-
- NOTES:
-
- - Needs some error handling, especially for the parted bits.
-
- """
- storage = installer.ds.storage
-
- # we are only interested in partitions that physically exist
- partitions = [p for p in storage.partitions if p.exists]
- disks = [] # a list of disks from which we've removed partitions
- clearparts = [] # list of partitions we'll remove
- for part in partitions:
- # if we got a list of disks to clear, make sure this one's on it
- if storage.clearDisks and part.disk.name not in storage.clearDisks:
- continue
-
- # don't clear partitions holding install media
- #if part.name in storage.protectedPartitions:
- # continue
-
- # we don't want to fool with extended partitions, freespace
- if part.partType not in (parted.PARTITION_NORMAL, parted.PARTITION_LOGICAL):
- continue
-
- # XXX is there any argument for not removing incomplete devices?
- # -- maybe some RAID devices
- devices = storage.deviceDeps(part)
- while devices:
- installer.log.debug("Devices to remove: %s" % ([d.name for d in devices],))
- leaves = [d for d in devices if d.isleaf]
- installer.log.debug("Leaves to remove: %s" % ([d.name for d in leaves],))
- for leaf in leaves:
- storage.destroyDevice(leaf)
- devices.remove(leaf)
-
- #installer.log.debug("Partitions left: %s" % [p.getDeviceNodeName() for p in part.partedPartition.disk.partitions])
- disk_name = os.path.basename(part.partedPartition.disk.device.path)
- if disk_name not in disks:
- disks.append(disk_name)
-
- clearparts.append(part)
-
- for part in clearparts:
- storage.destroyDevice(part)
-
- # now remove any empty extended partitions
- removeEmptyExtendedPartitions(installer)
-
-def removeEmptyExtendedPartitions(installer):
- storage = installer.ds.storage
- for disk in storage.disks:
- #installer.log.debug("Checking whether disk %s has an empty extended" % disk.name)
- extended = disk.partedDisk.getExtendedPartition()
- logical_parts = disk.partedDisk.getLogicalPartitions()
- #installer.log.debug("Extended is %s ; logicals is %s" % (extended, [p.getDeviceNodeName() for p in logical_parts]))
- if extended and not logical_parts:
- installer.log.debug("Removing empty extended partition from %s" % disk.name)
- extended_name = devicePathToName(extended.getDeviceNodeName())
- extended = storage.devicetree.getDeviceByName(extended_name)
- storage.destroyDevice(extended)
- #disk.partedDisk.removePartition(extended.partedPartition)
-
-def _createFreeSpacePartitions(installer):
- # get a list of disks that have at least one free space region of at
- # least 100MB
- disks = []
- for disk in installer.ds.storage.disks:
- if disk.name not in installer.ds.storage.clearDisks:
- continue
-
- partedDisk = disk.partedDisk
- part = disk.partedDisk.getFirstPartition()
- while part:
- if not part.type & parted.PARTITION_FREESPACE:
- part = part.nextPartition()
- continue
-
- if part.getSize(unit="MB") > 100:
- disks.append(disk)
- break
-
- part = part.nextPartition()
-
- # create a separate pv partition for each disk with free space
- devs = []
- for disk in disks:
- if installer.ds.storage.encryptedAutoPart:
- fmt_type = "luks"
- else:
- fmt_type = "lvmpv"
- part = installer.ds.storage.newPartition(fmt_type=fmt_type,
- size=1, grow=True,
- disks=[disk])
- installer.ds.storage.createDevice(part)
- devs.append(part)
-
- return (disks, devs)
-
-def _schedulePartitions(installer, disks):
- #
- # Convert storage.autoPartitionRequests into Device instances and
- # schedule them for creation
- #
- # First pass is for partitions only. We'll do LVs later.
- #
- for request in installer.ds.storage.autoPartitionRequests:
- if request.asVol:
- continue
-
- if request.fstype is None:
- request.fstype = installer.ds.storage.defaultFSType
-
- dev = installer.ds.storage.newPartition(fmt_type=request.fstype,
- size=request.size,
- grow=request.grow,
- maxsize=request.maxSize,
- mountpoint=request.mountpoint,
- disks=disks,
- weight=request.weight)
-
- # schedule the device for creation
- installer.ds.storage.createDevice(dev)
-
- # make sure preexisting broken lvm/raid configs get out of the way
- return
-
-def allocatePartitions(installer, disks, partitions):
- """ Allocate partitions based on requested features.
-
- Non-existing partitions are sorted according to their requested
- attributes, and then allocated.
-
- The basic approach to sorting is that the more specifically-
- defined a request is, the earlier it will be allocated. See
- the function partitionCompare for details on the sorting
- criteria.
-
- The PartitionDevice instances will have their name and parents
- attributes set once they have been allocated.
- """
- #installer.log.debug("disks=%s ; partitions=%s" % (disks, partitions))
- new_partitions = [p for p in partitions if not p.exists]
- new_partitions.sort(cmp=partitionCompare)
-
- # XXX is this needed anymore?
- partedDisks = {}
- for disk in disks:
- if disk.path not in partedDisks.keys():
- partedDisks[disk.path] = disk.partedDisk #.duplicate()
-
- # remove all newly added partitions from the disk
- installer.log.debug("Removing all non-preexisting from disk(s)")
- for _part in new_partitions:
- if _part.partedPartition:
- if _part.isExtended:
- continue # these get removed last
- #_part.disk.partedDisk.removePartition(_part.partedPartition)
- partedDisk = partedDisks[_part.disk.partedDisk.device.path]
- installer.log.debug("Removing part %s (%s) from disk %s (%s)" %
- (_part.partedPartition.path,
- [p.path for p in _part.partedPartition.disk.partitions],
- partedDisk.device.path,
- [p.path for p in partedDisk.partitions]))
-
- partedDisk.removePartition(_part.partedPartition)
- _part.partedPartition = None
- _part.disk = None
-
- # remove empty extended so it doesn't interfere
- extended = partedDisk.getExtendedPartition()
- if extended and not partedDisk.getLogicalPartitions():
- installer.log.debug("Removing empty extended partition")
- #partedDisk.minimizeExtendedPartition()
- partedDisk.removePartition(extended)
-
- for _part in new_partitions:
- if _part.partedPartition and _part.isExtended:
- # ignore new extendeds as they are implicit requests
- continue
-
- # obtain the set of candidate disks
- req_disks = []
- if _part.disk:
- # we have a already selected a disk for this request
- req_disks = [_part.disk]
- elif _part.req_disks:
- # use the requested disk set
- req_disks = _part.req_disks
- else:
- # no disks specified means any disk will do
- req_disks = disks
-
- #installer.log.debug("allocating partition: %s ; disks: %s ; boot: %s ; "
- # "primary: %s ; size: %dMB ; grow: %s ; max_size: %s" %
- # (_part.name, req_disks, _part.req_bootable, _part.req_primary,
- # _part.req_size, _part.req_grow, _part.req_max_size))
- free = None
- use_disk = None
- part_type = None
- # loop through disks
- for _disk in req_disks:
- disk = partedDisks[_disk.path]
- #for p in disk.partitions:
- # installer.log.debug("disk %s: part %s" % (disk.device.path, p.path))
- sectorSize = disk.device.physicalSectorSize
- best = None
-
- #installer.log.debug("Checking freespace on %s" % _disk.name)
-
- new_part_type = getNextPartitionType(disk)
- if new_part_type is None:
- # can't allocate any more partitions on this disk
- installer.log.debug("No free partition slots on %s" % _disk.name)
- continue
-
- if _part.req_primary and new_part_type != parted.PARTITION_NORMAL:
- # we need a primary slot and none are free on this disk
- installer.log.debug("No primary slots available on %s" % _disk.name)
- continue
-
- best = getBestFreeSpaceRegion(installer, disk,
- new_part_type,
- _part.req_size,
- best_free=free,
- boot=_part.req_bootable)
-
- if best == free and not _part.req_primary and \
- new_part_type == parted.PARTITION_NORMAL:
- # see if we can do better with a logical partition
- installer.log.debug("Not enough free space for primary -- trying logical")
- new_part_type = getNextPartitionType(disk, no_primary=True)
- if new_part_type:
- best = getBestFreeSpaceRegion(disk,
- new_part_type,
- _part.req_size,
- best_free=free,
- boot=_part.req_bootable)
-
- if best and free != best:
- # now we know we are choosing a new free space,
- # so update the disk and part type
- #installer.log.debug("Updating use_disk to %s (%s), type: %s"
- # % (_disk, _disk.name, new_part_type))
- part_type = new_part_type
- use_disk = _disk
- installer.log.debug("New free: %s (%d-%d / %dMB)" % (best.device.path,
- best.start,
- best.end,
- best.getSize()))
- free = best
-
- if free and _part.req_bootable:
- # if this is a bootable partition we want to
- # use the first freespace region large enough
- # to satisfy the request
- installer.log.debug("Found free space for bootable request")
- break
-
- if free is None:
- raise PartitioningError("Not enough free space on disks")
-
- _disk = use_disk
- disk = _disk.partedDisk
-
- # create the extended partition if needed
- # TODO: move to a function (disk, free)
- if part_type == parted.PARTITION_EXTENDED:
- installer.log.debug("Creating extended partition")
- geometry = parted.Geometry(device=disk.device,
- start=free.start,
- length=free.length,
- end=free.end)
- extended = parted.Partition(disk=disk,
- type=parted.PARTITION_EXTENDED,
- geometry=geometry)
- constraint = parted.Constraint(device=disk.device)
- # FIXME: we should add this to the tree as well
- disk.addPartition(extended, constraint)
-
- # end proposed function
-
- # now the extended partition exists, so set type to logical
- part_type = parted.PARTITION_LOGICAL
-
- # recalculate freespace
- installer.log.debug("Recalculating free space")
- free = getBestFreeSpaceRegion(disk,
- part_type,
- _part.req_size,
- boot=_part.req_bootable)
- if not free:
- raise PartitioningError("Not enough free space after "
- "creating extended partition")
-
- # create minimum geometry for this request
- # req_size is in MB
- sectors_per_track = disk.device.biosGeometry[2]
- length = (_part.req_size * (1024 * 1024)) / sectorSize
- new_geom = parted.Geometry(device=disk.device,
- start=max(sectors_per_track, free.start),
- length=length)
-
- # create maximum and minimum geometries for constraint
- start = max(0 , free.start - 1)
- max_geom = parted.Geometry(device=disk.device,
- start=start,
- length=min(length + 1, disk.device.length - start))
- min_geom = parted.Geometry(device=disk.device,
- start=free.start + 1,
- length=length-1)
-
-
- # create the partition and add it to the disk
- partition = parted.Partition(disk=disk,
- type=part_type,
- geometry=new_geom)
- constraint = parted.Constraint(maxGeom=max_geom, minGeom=min_geom)
- disk.addPartition(partition=partition,
- constraint=constraint)
- installer.log.debug("Created partition %s of %dMB and added it to %s" %
- (partition.getDeviceNodeName(), partition.getSize(), disk.device.path))
-
- # this one sets the name
- _part.partedPartition = partition
- _part.disk = _disk
-
- # parted modifies the partition in the process of adding it to
- # the disk, so we need to grab the latest version...
- _part.partedPartition = disk.getPartitionByPath(_part.path)
-
-def growPartitions(installer, disks, partitions):
- """ Grow all growable partition requests.
-
- All requests should know what disk they will be on by the time
- this function is called. This is reflected in the
- PartitionDevice's disk attribute. Note that the req_disks
- attribute remains unchanged.
-
- The total available free space is summed up for each disk and
- partition requests are allocated a maximum percentage of the
- available free space on their disk based on their own base size.
-
- Each attempted size means calling allocatePartitions again with
- one request's size having changed.
-
- After taking into account several factors that may limit the
- maximum size of a requested partition, we arrive at a firm
- maximum number of sectors by which a request can potentially grow.
-
- An initial attempt is made to allocate the full maximum size. If
- this fails, we begin a rough binary search with a maximum of three
- iterations to settle on a new size.
-
- Arguments:
-
- disks -- a list of all usable disks (DiskDevice instances)
- partitions -- a list of all partitions (PartitionDevice
- instances)
- """
- #installer.log.debug("growPartitions: disks=%s, partitions=%s" %
- # ([d.name for d in disks], [p.name for p in partitions]))
- all_growable = [p for p in partitions if p.req_grow]
- if not all_growable:
- return
-
- # sort requests by base size in decreasing order
- all_growable.sort(key=lambda p: p.req_size, reverse=True)
-
- installer.log.debug("Growable requests are %s" % [p.name for p in all_growable])
-
- for disk in disks:
- installer.log.debug("Growing requests on %s" % disk.name)
- for p in disk.partedDisk.partitions:
- installer.log.debug(" %s: %s (%dMB)" % (disk.name, p.getDeviceNodeName(),
- p.getSize()))
- sectorSize = disk.partedDisk.device.physicalSectorSize
- # get a list of free space regions on the disk
- free = disk.partedDisk.getFreeSpaceRegions()
- if not free:
- installer.log.debug("No free space on %s" % disk.name)
- continue
-
- # sort the free regions in decreasing order of size
- free.sort(key=lambda r: r.length, reverse=True)
- disk_free = reduce(lambda x,y: x + y, [f.length for f in free])
- installer.log.debug("Total free: %d sectors ; largest: %d sectors (%dMB)"
- % (disk_free, free[0].length, free[0].getSize()))
-
- # make a list of partitions currently allocated on this disk
- # -- they're already sorted
- growable = []
- disk_total = 0
- for part in all_growable:
- #log.debug("checking if part %s (%s) is on this disk" % (part.name,
- # part.disk.name))
- if part.disk == disk:
- growable.append(part)
- disk_total += part.partedPartition.geometry.length
- installer.log.debug("Add %s (%dMB/%d sectors) to growable total"
- % (part.name, part.partedPartition.getSize(),
- part.partedPartition.geometry.length))
- installer.log.debug("Growable total is now %d sectors" % disk_total)
-
- # now we loop through the partitions...
- # this first loop is to identify obvious chunks of free space that
- # will be left over due to max size
- leftover = 0
- limited = {}
- unlimited_total = 0
- for part in growable:
- # calculate max number of sectors this request can grow
- req_sectors = part.partedPartition.geometry.length
- share = float(req_sectors) / float(disk_total)
- max_grow = (share * disk_free)
- max_sectors = req_sectors + max_grow
- limited[part.name] = False
-
- if part.req_max_size:
- req_max_sect = (part.req_max_size * (1024 * 1024)) / sectorSize
- if req_max_sect < max_sectors:
- mb = ((max_sectors - req_max_sect) * sectorSize) / (1024*1024)
-
- installer.log.debug("Adding %dMB to leftovers from %s"
- % (mb, part.name))
- leftover += (max_sectors - req_max_sect)
- limited[part.name] = True
-
- if not limited[part.name]:
- unlimited_total += req_sectors
-
- # now we loop through the partitions...
- for part in growable:
- # calculate max number of sectors this request can grow
- req_sectors = part.partedPartition.geometry.length
- share = float(req_sectors) / float(disk_total)
- max_grow = (share * disk_free)
- if not limited[part.name]:
- leftover_share = float(req_sectors) / float(unlimited_total)
- max_grow += leftover_share * leftover
- max_sectors = req_sectors + max_grow
- max_mb = (max_sectors * sectorSize) / (1024 * 1024)
-
- installer.log.debug("%s: base_size=%dMB, max_size=%sMB" %
- (part.name, part.req_base_size, part.req_max_size))
- installer.log.debug("%s: current_size=%dMB (%d sectors)" %
- (part.name, part.partedPartition.getSize(),
- part.partedPartition.geometry.length))
- installer.log.debug("%s: %dMB (%d sectors, or %d%% of %d)" %
- (part.name, max_mb, max_sectors, share * 100, disk_free))
-
- installer.log.debug("Checking constraints on max size...")
- # don't grow beyond the request's maximum size
- if part.req_max_size:
- installer.log.debug("max_size: %dMB" % part.req_max_size)
- # FIXME: round down to nearest cylinder boundary
- req_max_sect = (part.req_max_size * (1024 * 1024)) / sectorSize
- if req_max_sect < max_sectors:
- max_grow -= (max_sectors - req_max_sect)
- max_sectors = req_sectors + max_grow
-
- # don't grow beyond the resident filesystem's max size
- if part.format.maxSize > 0:
- installer.log.debug("Format maxsize: %dMB" % part.format.maxSize)
- # FIXME: round down to nearest cylinder boundary
- fs_max_sect = (part.format.maxSize * (1024 * 1024)) / sectorSize
- if fs_max_sect < max_sectors:
- max_grow -= (max_sectors - fs_max_sect)
- max_sectors = req_sectors + max_grow
-
- # we can only grow as much as the largest free region on the disk
- if free[0].length < max_grow:
- installer.log.debug("Largest free region: %d sectors (%dMB)" %
- (free[0].length, free[0].getSize()))
- # FIXME: round down to nearest cylinder boundary
- max_grow = free[0].length
- max_sectors = req_sectors + max_grow
-
- # Now, we try to grow this partition as close to max_grow
- # sectors as we can.
- #
- # We could call allocatePartitions after modifying this
- # request and saving the original value of part.req_size,
- # or we could try to use disk.maximizePartition().
- max_size = (max_sectors * sectorSize) / (1024 * 1024)
- orig_size = part.req_size
- # try the max size to begin with
- installer.log.debug("Attempting to allocate maximum size: %dMB" % max_size)
- part.req_size = max_size
- try:
- allocatePartitions(installer, disks, partitions)
- except PartitioningError, e:
- installer.log.debug("Max size attempt failed: %s (%dMB)" % (part.name,
- max_size))
- part.req_size = orig_size
- else:
- continue
-
- installer.log.debug("Starting binary search: size=%d max_size=%d" % (part.req_size, max_size))
- count = 0
- op_func = add
- increment = max_grow
- last_good_size = part.req_size
- last_outcome = None
- while count < 3:
- last_size = part.req_size
- increment /= 2
- req_sectors = op_func(req_sectors, increment)
- part.req_size = (req_sectors * sectorSize) / (1024 * 1024)
- installer.log.debug("Attempting size=%dMB" % part.req_size)
- count += 1
- try:
- allocatePartitions(disks, partitions)
- except PartitioningError, e:
- installer.log.debug("Attempt at %dMB failed" % part.req_size)
- op_func = sub
- last_outcome = False
- else:
- op_func = add
- last_good_size = part.req_size
- last_outcome = True
-
- if not last_outcome:
- part.req_size = last_good_size
- installer.log.debug("Backing up to size=%dMB" % part.req_size)
- try:
- allocatePartitions(disks, partitions)
- except PartitioningError, e:
- raise PartitioningError("Failed to grow partitions")
-
- # reset all requests to their original requested size
- for part in partitions:
- if part.exists:
- continue
- part.req_size = part.req_base_size
-
-def growLVM(installer):
- """ Grow LVs according to the sizes of the PVs. """
- storage = installer.ds.storage
- for vg in storage.vgs:
- total_free = vg.freeSpace
- if not total_free:
- installer.log.debug("vg %s has no free space" % vg.name)
- continue
-
- installer.log.debug("vg %s: %dMB free ; lvs: %s" % (vg.name, vg.freeSpace,
- [l.lvname for l in vg.lvs]))
-
- # figure out how much to grow each LV
- grow_amounts = {}
- lv_total = vg.size - total_free
- installer.log.debug("used: %dMB ; vg.size: %dMB" % (lv_total, vg.size))
-
- # This first loop is to calculate percentage-based growth
- # amounts. These are based on total free space.
- lvs = vg.lvs
- lvs.sort(cmp=lvCompare)
- for lv in lvs:
- if not lv.req_grow or not lv.req_percent:
- continue
-
- portion = (lv.req_percent * 0.01)
- grow = portion * vg.vgFree
- new_size = lv.req_size + grow
- if lv.req_max_size and new_size > lv.req_max_size:
- grow -= (new_size - lv.req_max_size)
-
- if lv.format.maxSize and lv.format.maxSize < new_size:
- grow -= (new_size - lv.format.maxSize)
-
- # clamp growth amount to a multiple of vg extent size
- grow_amounts[lv.name] = vg.align(grow)
- total_free -= grow
- lv_total += grow
-
- # This second loop is to calculate non-percentage-based growth
- # amounts. These are based on free space remaining after
- # calculating percentage-based growth amounts.
-
- # keep a tab on space not allocated due to format or requested
- # maximums -- we'll dole it out to subsequent requests
- leftover = 0
- for lv in lvs:
- installer.log.debug("Checking lv %s: req_grow: %s ; req_percent: %s"
- % (lv.name, lv.req_grow, lv.req_percent))
- if not lv.req_grow or lv.req_percent:
- continue
-
- portion = float(lv.req_size) / float(lv_total)
- grow = portion * total_free
- installer.log.debug("grow is %dMB" % grow)
-
- todo = lvs[lvs.index(lv):]
- unallocated = reduce(lambda x,y: x+y,
- [l.req_size for l in todo
- if l.req_grow and not l.req_percent])
- extra_portion = float(lv.req_size) / float(unallocated)
- extra = extra_portion * leftover
- installer.log.debug("%s getting %dMB (%d%%) of %dMB leftover space"
- % (lv.name, extra, extra_portion * 100, leftover))
- leftover -= extra
- grow += extra
- installer.log.debug("grow is now %dMB" % grow)
- max_size = lv.req_size + grow
- if lv.req_max_size and max_size > lv.req_max_size:
- max_size = lv.req_max_size
-
- if lv.format.maxSize and max_size > lv.format.maxSize:
- max_size = lv.format.maxSize
-
- installer.log.debug("max size is %dMB" % max_size)
- max_size = max_size
- leftover += (lv.req_size + grow) - max_size
- grow = max_size - lv.req_size
- installer.log.debug("lv %s gets %dMB" % (lv.name, vg.align(grow)))
- grow_amounts[lv.name] = vg.align(grow)
-
- if not grow_amounts:
- installer.log.debug("No growable lvs in vg %s" % vg.name)
- continue
-
- # now grow the lvs by the amounts we've calculated above
- for lv in lvs:
- if lv.name not in grow_amounts.keys():
- continue
- lv.size += grow_amounts[lv.name]
-
- # now there shouldn't be any free space left, but if there is we
- # should allocate it to one of the LVs
- vg_free = vg.freeSpace
- installer.log.debug("vg %s has %dMB free" % (vg.name, vg_free))
- if vg_free:
- for lv in lvs:
- if not lv.req_grow:
- continue
-
- if lv.req_max_size and lv.size == lv.req_max_size:
- continue
-
- if lv.format.maxSize and lv.size == lv.format.maxSize:
- continue
-
- # first come, first served
- projected = lv.size + vg.freeSpace
- if lv.req_max_size and projected > lv.req_max_size:
- projected = lv.req_max_size
-
- if lv.format.maxSize and projected > lv.format.maxSize:
- projected = lv.format.maxSize
-
- installer.log.debug("Giving leftover %dMB to %s" % (projected - lv.size,
- lv.name))
- lv.size = projected
-
-def partitionCompare(part1, part2):
- """ More specifically defined partitions come first.
-
- < 1 => x < y
- 0 => x == y
- > 1 => x > y
- """
- ret = 0
-
- if part1.req_base_weight:
- ret -= part1.req_base_weight
-
- if part2.req_base_weight:
- ret += part2.req_base_weight
-
- # bootable partitions to the front
- ret -= cmp(part1.req_bootable, part2.req_bootable) * 1000
-
- # more specific disk specs to the front of the list
- ret += cmp(len(part1.parents), len(part2.parents)) * 500
-
- # primary-only to the front of the list
- ret -= cmp(part1.req_primary, part2.req_primary) * 200
-
- # larger requests go to the front of the list
- ret -= cmp(part1.size, part2.size) * 100
-
- # fixed size requests to the front
- ret += cmp(part1.req_grow, part2.req_grow) * 50
-
- # potentially larger growable requests go to the front
- if part1.req_grow and part2.req_grow:
- if not part1.req_max_size and part2.req_max_size:
- ret -= 25
- elif part1.req_max_size and not part2.req_max_size:
- ret += 25
- else:
- ret -= cmp(part1.req_max_size, part2.req_max_size) * 25
-
- if ret > 0:
- ret = 1
- elif ret < 0:
- ret = -1
-
- return ret
-
-def lvCompare(lv1, lv2):
- """ More specifically defined lvs come first.
-
- < 1 => x < y
- 0 => x == y
- > 1 => x > y
- """
- ret = 0
-
- # larger requests go to the front of the list
- ret -= cmp(lv1.size, lv2.size) * 100
-
- # fixed size requests to the front
- ret += cmp(lv1.req_grow, lv2.req_grow) * 50
-
- # potentially larger growable requests go to the front
- if lv1.req_grow and lv2.req_grow:
- if not lv1.req_max_size and lv2.req_max_size:
- ret -= 25
- elif lv1.req_max_size and not lv2.req_max_size:
- ret += 25
- else:
- ret -= cmp(lv1.req_max_size, lv2.req_max_size) * 25
-
- if ret > 0:
- ret = 1
- elif ret < 0:
- ret = -1
-
- return ret
-
-def getNextPartitionType(disk, no_primary=None):
- """ Find the type of partition to create next on a disk.
-
- Return a parted partition type value representing the type of the
- next partition we will create on this disk.
-
- If there is only one free primary partition and we can create an
- extended partition, we do that.
-
- If there are free primary slots and an extended partition we will
- recommend creating a primary partition. This can be overridden
- with the keyword argument no_primary.
-
- Arguments:
-
- disk -- a parted.Disk instance representing the disk
-
- Keyword arguments:
-
- no_primary -- given a choice between primary and logical
- partitions, prefer logical
-
- """
- part_type = None
- extended = disk.getExtendedPartition()
- supports_extended = disk.supportsFeature(parted.DISK_TYPE_EXTENDED)
- logical_count = len(disk.getLogicalPartitions())
- max_logicals = disk.getMaxLogicalPartitions()
- primary_count = disk.primaryPartitionCount
-
- if primary_count == disk.maxPrimaryPartitionCount and \
- extended and logical_count < max_logicals:
- part_type = parted.PARTITION_LOGICAL
- elif primary_count == (disk.maxPrimaryPartitionCount - 1) and \
- not extended and supports_extended:
- # last chance to create an extended partition
- part_type = parted.PARTITION_EXTENDED
- elif no_primary and extended and logical_count < max_logicals:
- # create a logical even though we could presumably create a
- # primary instead
- part_type = parted.PARTITION_LOGICAL
- elif not no_primary:
- # XXX there is a possiblity that the only remaining free space on
- # the disk lies within the extended partition, but we will
- # try to create a primary first
- part_type = parted.PARTITION_NORMAL
-
- return part_type
-
-def getBestFreeSpaceRegion(installer, disk, part_type, req_size,
- boot=None, best_free=None):
- """ Return the "best" free region on the specified disk.
-
- For non-boot partitions, we return the largest free region on the
- disk. For boot partitions, we return the first region that is
- large enough to hold the partition.
-
- Partition type (parted's PARTITION_NORMAL, PARTITION_LOGICAL) is
- taken into account when locating a suitable free region.
-
- For locating the best region from among several disks, the keyword
- argument best_free allows the specification of a current "best"
- free region with which to compare the best from this disk. The
- overall best region is returned.
-
- Arguments:
-
- disk -- the disk (a parted.Disk instance)
- part_type -- the type of partition we want to allocate
- (one of parted's partition type constants)
- req_size -- the requested size of the partition (in MB)
-
- Keyword arguments:
-
- boot -- indicates whether this will be a bootable partition
- (boolean)
- best_free -- current best free region for this partition
-
- """
- #installer.log.debug("getBestFreeSpaceRegion: disk=%s part_type=%d req_size=%dMB boot=%s best=%s" %
- # (disk.device.path, part_type, req_size, boot, best_free))
- extended = disk.getExtendedPartition()
- for _range in disk.getFreeSpaceRegions():
- if extended:
- # find out if there is any overlap between this region and the
- # extended partition
- installer.log.debug("Looking for intersection between extended (%d-%d) and free (%d-%d)" %
- (extended.geometry.start, extended.geometry.end, _range.start, _range.end))
-
- # parted.Geometry.overlapsWith can handle this
- try:
- free_geom = extended.geometry.intersect(_range)
- except ArithmeticError, e:
- # this freespace region does not lie within the extended
- # partition's geometry
- free_geom = None
-
- if (free_geom and part_type == parted.PARTITION_NORMAL) or \
- (not free_geom and part_type == parted.PARTITION_LOGICAL):
- installer.log.debug("Free region not suitable for request")
- continue
-
- if part_type == parted.PARTITION_NORMAL:
- # we're allocating a primary and the region is not within
- # the extended, so we use the original region
- free_geom = _range
- else:
- free_geom = _range
-
- installer.log.debug("Current free range on %s is %d-%d (%dMB)" % (disk.device.path,
- free_geom.start,
- free_geom.end,
- free_geom.getSize()))
- free_size = free_geom.getSize()
-
- if req_size <= free_size:
- if not best_free or free_geom.length > best_free.length:
- best_free = free_geom
-
- if boot:
- # if this is a bootable partition we want to
- # use the first freespace region large enough
- # to satisfy the request
- break
-
- return best_free
-
-def _scheduleLVs(installer, devs):
- if installer.ds.storage.encryptedAutoPart:
- pvs = []
- for dev in devs:
- pv = LUKSDevice("luks-%s" % dev.name,
- format=getFormat("lvmpv", device=dev.path),
- size=dev.size,
- parents=dev)
- pvs.append(pv)
- installer.ds.storage.createDevice(pv)
- else:
- pvs = devs
-
- # create a vg containing all of the autopart pvs
- vg = installer.ds.storage.newVG(pvs=pvs)
- installer.ds.storage.createDevice(vg)
-
- #
- # Convert storage.autoPartitionRequests into Device instances and
- # schedule them for creation.
- #
- # Second pass, for LVs only.
- for request in installer.ds.storage.autoPartitionRequests:
- if not request.asVol:
- continue
-
- if request.fstype is None:
- request.fstype = installer.ds.storage.defaultFSType
-
- # FIXME: move this to a function and handle exceptions
- dev = installer.ds.storage.newLV(vg=vg,
- fmt_type=request.fstype,
- mountpoint=request.mountpoint,
- grow=request.grow,
- maxsize=request.maxSize,
- size=request.size)
-
- # schedule the device for creation
- installer.ds.storage.createDevice(dev)
+++ /dev/null
-#!/usr/bin/python
-
-import os
-import sys
-
-import util
-
-def udev_settle(timeout=None):
- argv = ["settle"]
- if timeout:
- argv.append("--timeout=%d" % int(timeout))
-
- util.execWithRedirect("udevadm", argv, stderr="/dev/null", searchPath=1)
-
-def udev_trigger(subsystem=None):
- argv = ["trigger"]
- if subsystem:
- argv.append("--subsystem-match=%s" % subsystem)
-
- util.execWithRedirect("udevadm", argv, stderr="/dev/null", searchPath=1)
-
-def udev_get_block_devices():
- #udev_settle(timeout=30)
- entries = []
- for path in enumerate_block_devices():
- entry = udev_get_block_device(path)
- if entry:
- entries.append(entry)
- return entries
-
-def __is_blacklisted_blockdev(dev_name):
- """Is this a blockdev we never want for an install?"""
- if dev_name.startswith("loop") or dev_name.startswith("ram") or dev_name.startswith("fd"):
- return True
-
- if os.path.exists("/sys/class/block/%s/device/model" %(dev_name,)):
- model = open("/sys/class/block/%s/device/model" %(dev_name,)).read()
- for bad in ("IBM *STMF KERNEL", "SCEI Flash-5", "DGC LUNZ"):
- if model.find(bad) != -1:
- return True
-
- return False
-
-def enumerate_block_devices():
- top_dir = "/sys/class/block"
- devices = []
- for dev_name in os.listdir(top_dir):
- if __is_blacklisted_blockdev(dev_name):
- continue
- full_path = os.path.join(top_dir, dev_name)
- link_ref = os.readlink(full_path)
- real_path = os.path.join(top_dir, link_ref)
- sysfs_path = os.path.normpath(real_path)
- devices.append(sysfs_path)
- return devices
-
-def udev_get_block_device(sysfs_path):
- if not os.path.exists(sysfs_path):
- return None
-
- db_entry = sysfs_path[4:].replace("/", "\\x2f")
- db_root = "/dev/.udev/db"
- db_path = os.path.normpath("%s/%s" % (db_root, db_entry))
- if not os.access(db_path, os.R_OK):
- return None
-
- entry = open(db_path).read()
- dev = udev_parse_block_entry(entry)
- if dev:
- # XXX why do we do this? is /sys going to move during installation?
- dev['sysfs_path'] = sysfs_path[4:] # strip off the leading '/sys'
- dev = udev_parse_uevent_file(dev)
-
- # now add in the contents of the uevent file since they're handy
- return dev
-
-def udev_parse_uevent_file(dev):
- path = os.path.normpath("/sys/%s/uevent" % dev['sysfs_path'])
- if not os.access(path, os.R_OK):
- return dev
-
- with open(path) as f:
- for line in f.readlines():
- (key, equals, value) = line.strip().partition("=")
- if not equals:
- continue
- dev[key] = value
-
- return dev
-
-def udev_parse_block_entry(buf):
- dev = {'name': None,
- 'symlinks': []}
-
- for line in buf.splitlines():
- line.strip()
- (tag, sep, val) = line.partition(":")
- if not sep:
- continue
-
- if tag == "N":
- dev['name'] = val
- elif tag == "S":
- dev['symlinks'].append(val)
- elif tag == "E":
- if val.count("=") > 1 and val.count(" ") > 0:
- # eg: LVM2_LV_NAME when querying the VG for its LVs
- vars = val.split()
- vals = []
- var_name = None
- for (index, subval) in enumerate(vars):
- (var_name, sep, var_val) = subval.partition("=")
- if sep:
- vals.append(var_val)
-
- dev[var_name] = vals
- else:
- (var_name, sep, var_val) = val.partition("=")
- if not sep:
- continue
-
- if var_val.count(" "):
- # eg: DEVLINKS
- var_val = var_val.split()
-
- dev[var_name] = var_val
-
- if dev.get("name"):
- return dev
-
-# These are functions for retrieving specific pieces of information from
-# udev database entries.
-def udev_device_get_name(udev_info):
- """ Return the best name for a device based on the udev db data. """
- return udev_info.get("DM_NAME", udev_info["name"])
-
-def udev_device_get_format(udev_info):
- """ Return a device's format type as reported by udev. """
- return udev_info.get("ID_FS_TYPE")
-
-def udev_device_get_uuid(udev_info):
- """ Get the UUID from the device's format as reported by udev. """
- md_uuid = udev_info.get("MD_UUID")
- uuid = udev_info.get("ID_FS_UUID")
- # we don't want to return the array's uuid as a member's uuid
- if uuid and not md_uuid == uuid:
- return udev_info.get("ID_FS_UUID")
-
-def udev_device_get_label(udev_info):
- """ Get the label from the device's format as reported by udev. """
- return udev_info.get("ID_FS_LABEL")
-
-def udev_device_is_dm(info):
- """ Return True if the device is a device-mapper device. """
- return info.has_key("DM_NAME")
-
-def udev_device_is_md(info):
- """ Return True is the device is an mdraid array device. """
- return info.has_key("MD_METADATA")
-
-def udev_device_is_cdrom(info):
- """ Return True if the device is an optical drive. """
- # FIXME: how can we differentiate USB drives from CD-ROM drives?
- # -- USB drives also generate a sdX device.
- return info.get("ID_CDROM") == "1"
-
-def udev_device_is_disk(info):
- """ Return True is the device is a disk. """
- has_range = os.path.exists("/sys/%s/range" % info['sysfs_path'])
- return info.get("DEVTYPE") == "disk" or has_range
-
-def udev_device_is_partition(info):
- has_start = os.path.exists("/sys/%s/start" % info['sysfs_path'])
- return info.get("DEVTYPE") == "partition" or has_start
-
-def udev_device_get_sysfs_path(info):
- return info['sysfs_path']
-
-def udev_device_get_major(info):
- return int(info["MAJOR"])
-
-def udev_device_get_minor(info):
- return int(info["MINOR"])
-
-def udev_device_get_md_level(info):
- return info["MD_LEVEL"]
-
-def udev_device_get_md_devices(info):
- return int(info["MD_DEVICES"])
-
-def udev_device_get_md_uuid(info):
- return info["MD_UUID"]
-
-def udev_device_get_vg_name(info):
- return info['LVM2_VG_NAME']
-
-def udev_device_get_vg_uuid(info):
- return info['LVM2_VG_UUID']
-
-def udev_device_get_vg_size(info):
- # lvm's decmial precision is not configurable, so we tell it to use
- # KB and convert to MB here
- return float(info['LVM2_VG_SIZE']) / 1024
-
-def udev_device_get_vg_free(info):
- # lvm's decmial precision is not configurable, so we tell it to use
- # KB and convert to MB here
- return float(info['LVM2_VG_FREE']) / 1024
-
-def udev_device_get_vg_extent_size(info):
- # lvm's decmial precision is not configurable, so we tell it to use
- # KB and convert to MB here
- return float(info['LVM2_VG_EXTENT_SIZE']) / 1024
-
-def udev_device_get_vg_extent_count(info):
- return int(info['LVM2_VG_EXTENT_COUNT'])
-
-def udev_device_get_vg_free_extents(info):
- return int(info['LVM2_VG_FREE_COUNT'])
-
-def udev_device_get_vg_pv_count(info):
- return int(info['LVM2_PV_COUNT'])
-
-def udev_device_get_pv_pe_start(info):
- # lvm's decmial precision is not configurable, so we tell it to use
- # KB and convert to MB here
- return float(info['LVM2_PE_START']) / 1024
-
-def udev_device_get_lv_names(info):
- names = info['LVM2_LV_NAME']
- if not names:
- names = []
- elif not isinstance(names, list):
- names = [names]
- return names
-
-def udev_device_get_lv_uuids(info):
- uuids = info['LVM2_LV_UUID']
- if not uuids:
- uuids = []
- elif not isinstance(uuids, list):
- uuids = [uuids]
- return uuids
-
-def udev_device_get_lv_sizes(info):
- # lvm's decmial precision is not configurable, so we tell it to use
- # KB and convert to MB here
- sizes = info['LVM2_LV_SIZE']
- if not sizes:
- sizes = []
- elif not isinstance(sizes, list):
- sizes = [sizes]
-
- return [float(s) / 1024 for s in sizes]
-
-def udev_device_is_dmraid(info):
- # Note that this function does *not* identify raid sets.
- # Tests to see if device is parto of a dmraid set.
- # dmraid and mdriad have the same ID_FS_USAGE string, ID_FS_TYPE has a
- # string that describes the type of dmraid (isw_raid_member...), I don't
- # want to maintain a list and mdraid's ID_FS_TYPE='linux_raid_member', so
- # dmraid will be everything that is raid and not linux_raid_member
- #from formats.dmraid import DMRaidMember
- #if info.has_key("ID_FS_TYPE") and \
- # info["ID_FS_TYPE"] in DMRaidMember._udevTypes:
- # return True
- #
- return False
-
-def udev_device_get_dmraid_partition_disk(info):
- try:
- p_index = info["DM_NAME"].rindex("p")
- except (KeyError, AttributeError, ValueError):
- return None
-
- if not info["DM_NAME"][p_index+1:].isdigit():
- return None
-
- return info["DM_NAME"][:p_index]
-
-def udev_device_is_dmraid_partition(info, devicetree):
- #diskname = udev_device_get_dmraid_partition_disk(info)
- #dmraid_devices = devicetree.getDevicesByType("dm-raid array")
- #
- #for device in dmraid_devices:
- # if diskname == device.name:
- # return True
- #
- return False
-
-if __name__ == "__main__":
- for device in udev_get_block_devices():
- print udev_device_get_name(device)
- print " Label :", udev_device_get_label(device)
- print " UUID :", udev_device_get_uuid(device)
- print " Format :", udev_device_get_format(device)
- print " Is disk :", udev_device_is_disk(device)
- print " Is cdrom:", udev_device_is_cdrom(device)
- print " Is part :", udev_device_is_partition(device)
- print " Is dm :", udev_device_is_dm(device)
- print " Is md :", udev_device_is_md(device)
- #syspath = "/sys" + udev_device_get_sysfs_path(device)
- #for (key, value) in udev_get_block_device(syspath).items():
- # print " (%s : %s)" % (key, value,)
- print
+++ /dev/null
-#!/usr/bin/python
-
-import string
-
-from snack import *
-from constants import *
-
-import gettext
-_ = lambda x: gettext.ldgettext("pomona", x)
-
-class TextWindow:
- def __init__(self, screen):
- self.screen = screen
-
- def pop(self):
- self.screen.popWindow()
- self.screen.refresh()
-
- def refresh(self):
- self.screen.refresh()
-
-
-class WaitWindow(TextWindow):
- def setText(self, text):
- self.t.setText(text)
- self.g.draw()
- self.screen.refresh()
-
- def __init__(self, screen, title, text, width):
- TextWindow.__init__(self, screen)
-
- if width is None:
- width = 40
- if (len(text) < width):
- width = len(text)
-
- self.t = TextboxReflowed(width, text)
-
- self.g = GridForm(self.screen, title, 1, 1)
- self.g.add(self.t, 0, 0)
- self.g.draw()
- self.screen.refresh()
-
-
-class OkCancelWindow:
- def getrc(self):
- return self.rc
-
- def __init__(self, screen, title, text):
- rc = ButtonChoiceWindow(screen, title, text, buttons=[TEXT_OK_BUTTON, _("Cancel")])
- if rc == string.lower(_("Cancel")):
- self.rc = 1
- else:
- self.rc = 0
-
-
-class ExceptionWindow(TextWindow):
- def __init__ (self, short, long=None, screen=None):
- TextWindow.__init__(self, screen)
- self.text = "%s\n\n" % short
- self.buttons=[TEXT_OK_BUTTON]
-
- def run(self):
- self.rc = ButtonChoiceWindow(self.screen, _("Exception Occurred"),
- self.text, self.buttons, width=60)
-
- def getrc(self):
- return 0
-
-
-class TextInterface:
- def __init__(self, log):
- self.log = log
- self.screen = SnackScreen()
-
- self.setRootline(SCREEN_ROOTLINE)
- self.setHelpline(SCREEN_HELPLINE)
-
- def __del__(self):
- if self.screen:
- self.screen.finish()
-
- def setRootline(self, msg):
- self.screen.drawRootText (0, 0, string.center(msg, self.screen.width))
- self.log.debug("Set rootline text: %s" % msg)
-
- def setHelpline(self, msg):
- self.screen.pushHelpLine(string.center(msg, self.screen.width))
- self.log.debug("Set helpline text: %s" % msg)
-
-
- ### WINDOW DEFINITIONS ###
-
- def waitWindow(self, title, text, width=None):
- return WaitWindow(self.screen, title, text, width)
-
- def exceptionWindow(self, short, long):
- self.log.critical(short)
- return ExceptionWindow(short, long, self.screen)
-
- def messageWindow(self, title, text, type="ok", default = None,
- custom_icon=None, custom_buttons=[]):
- if type == "ok":
- ButtonChoiceWindow(self.screen, title, text, buttons=[TEXT_OK_BUTTON])
-
- elif type == "yesno":
- if default and default == "no":
- btnlist = [TEXT_NO_BUTTON, TEXT_YES_BUTTON]
- else:
- btnlist = [TEXT_YES_BUTTON, TEXT_NO_BUTTON]
- rc = ButtonChoiceWindow(self.screen, title, text, buttons=btnlist)
- if rc == "yes":
- return 1
- else:
- return 0
-
- elif type == "custom":
- tmpbut = []
- for but in custom_buttons:
- tmpbut.append(string.replace(but,"_",""))
- rc = ButtonChoiceWindow(self.screen, title, text, width=60, buttons=tmpbut)
-
- idx = 0
- for b in tmpbut:
- if string.lower(b) == rc:
- return idx
- idx = idx + 1
- return 0
-
- else:
- return OkCancelWindow(self.screen, title, text)
+++ /dev/null
-#!/usr/bin/python
-
-import os
-import stat
-
-from pyfire.executil import *
-
-def getArch():
- return "i386"
-
-def notify_kernel(path, action="change"):
- """ Signal the kernel that the specified device has changed. """
- path = os.path.join(path, "uevent")
- if not path.startswith("/sys/") or not os.access(path, os.W_OK):
- raise ValueError("invalid sysfs path")
- f = open(path, "a")
- f.write("%s\n" % action)
- f.close()
-
-def numeric_type(num):
- """ Verify that a value is given as a numeric data type.
-
- Return the number if the type is sensible or raise ValueError
- if not.
- """
- if num is None:
- num = 0
- elif not (isinstance(num, int) or \
- isinstance(num, long) or \
- isinstance(num, float)):
- raise ValueError("value (%s) must be either a number or None" % num)
-
- return num
-
-## Create a directory path. Don't fail if the directory already exists.
-# @param dir The directory path to create.
-def mkdirChain(dir):
- try:
- os.makedirs(dir, 0755)
- except OSError, (errno, msg):
- try:
- if errno == EEXIST and stat.S_ISDIR(os.stat(dir).st_mode):
- return
- except:
- pass
+++ /dev/null
-#!/usr/bin/python
-
-import sys
-
-from snack import *
-from constants import *
-
-import gettext
-_ = lambda x: gettext.ldgettext("pomona", x)
-
-def welcomeWindow(installer):
- rc = installer.intf.messageWindow(_("%s") % PRODUCT_NAME,
- _("Welcome to %s-v%s!\n\n") % (PRODUCT_NAME, PRODUCT_VERSION,))
- return DISPATCH_FORWARD
-
-def experimentalWindow(installer):
- if installer.dispatch.dir == DISPATCH_BACK:
- return DISPATCH_NOOP
-
- # Check if we are running a pre-release version
- version = PRODUCT_VERSION
- if not version.find("alpha") and \
- not version.find("beta") and \
- not version.find("rc"):
- return DISPATCH_NOOP
-
- while 1:
- rc = installer.intf.messageWindow( _("Warning! This is pre-release software!"),
- _("Thank you for downloading this "
- "pre-release of %s.\n\n"
- "This is not a final "
- "release and is not intended for use "
- "on production systems. The purpose of "
- "this release is to collect feedback "
- "from testers, and it is not suitable "
- "for day to day usage.\n\n"
- "To report feedback, please visit:\n\n"
- " %s\n\n"
- "and file a report.\n")
- % (PRODUCT_NAME, PRODUCT_URL),
- type="custom", custom_buttons=[_("_Exit"), _("_Install anyway")])
-
- if not rc:
- rc = installer.intf.messageWindow(_("Rebooting System"),
- _("Your system will now be rebooted..."),
- type="custom", custom_buttons=[_("_Back"), _("_Reboot")])
- if rc:
- sys.exit(0)
- else:
- break
-
-def finishedWindow(installer):
- installer.intf.setHelpline(_("Press <Enter> to exit"))
-
- rc = installer.intf.messageWindow(_("Complete"),
- _("Congratulations, your %s installation is "
- "complete.\n\n"
- "Press <Enter> to end the installation process.\n\n"
- "For information on errata (updates and bug fixes), visit "
- "%s.\n\n") % (PRODUCT_NAME, PRODUCT_URL,),
- type="custom", custom_buttons=[_("Reboot")])
-
- return INSTALL_OK
-
-def partmethodWindow(installer):
- storage = installer.ds.storage
-
- if storage.checkNoDisks():
- sys.exit(0)
-
- # Resetting options
- storage.doAutoPart = False
-# installer.dispatch.skipStep("partition", skip=0)
-
- methods = [ _("Automatic partitioning"), _("Custom partitioning"),]
- default = methods[0] # first should be autopartitioning
-
- (button, choice) = ListboxChoiceWindow(installer.intf.screen,
- _("Partition Method"),
- _("Installation requires partitioning of your hard drive. "
- "The default option is suitable for most users. "
- "You can also choose to create your own custom layout."),
- methods, buttons = [TEXT_OK_BUTTON, TEXT_BACK_BUTTON],
- width = 60, default=default, height = len(methods))
-
- if button == TEXT_BACK_CHECK:
- return INSTALL_BACK
-
- if choice == 0:
- installer.ds.storage.doAutoPart = True
- #installer.dispatch.skipStep("partition", skip=1)
-
- installer.log.info("User has chosen \"%s\"" % methods[choice])
-
- return INSTALL_OK
-
-def autopartitionWindow(installer):
- storage = installer.ds.storage
- while 1:
- g = GridForm(installer.intf.screen, _("Device Selection"), 1, 6)
- txt = TextboxReflowed(65, _("Which drive(s) do you want to use for this installation?\n\n"
- "ALL DATA stored on the devices will be destroyed."))
- g.add(txt, 0, 0, (0, 0, 0, 0))
-
- drivelist = CheckboxTree(height=4, scroll=1)
- g.add(drivelist, 0, 4, (0, 1, 0, 0))
-
- bb = ButtonBar(installer.intf.screen, [ TEXT_OK_BUTTON, TEXT_BACK_BUTTON ])
- g.add(bb, 0, 5, (0,1,0,0))
-
- for disk in storage.disks:
- if not storage.clearDisks or len(storage.clearDisks) < 1:
- selected = 1
- else:
- if disk in storage.clearDisks: # XXX never matches...
- selected = 1
- else:
- selected = 0
-
- diskdesc = "%6s %8.0f MB (%s)" % (disk.name, disk.size, disk.model[:24],)
-
- drivelist.append(diskdesc, selected = selected)
-
- rc = g.run()
-
- installer.intf.screen.popWindow()
-
- if bb.buttonPressed(rc) == TEXT_BACK_CHECK:
- return INSTALL_BACK
-
- if len(drivelist.getSelection()) > 0:
- storage.clearDisks = map(lambda s: s.split()[0], drivelist.getSelection())
- else:
- storage.clearDisks = []
- installer.intf.messageWindow(_("No Drives Selected"),
- _("An error has occurred - no valid devices were "
- "selected on which to create the new file system. "
- "For the installation of %s, "
- "you have to select at least one drive.") % PRODUCT_NAME,
- type="ok")
-
- continue
-
- installer.log.info("User selected \"%s\"" % storage.clearDisks)
- break
-
- return INSTALL_OK
-
-def reviewlayoutWindow(installer):
- if installer.dispatch.dir == DISPATCH_BACK:
- return DISPATCH_NOOP
-
- rc = installer.intf.messageWindow(_("Review Partition Layout"),
- _("Review and modify partitioning layout?"),
- type = "yesno")
- if rc != 1:
- #installer.dispatch.skipStep("partition", skip=1)
- pass
-
- return INSTALL_OK
-
-def bootloaderWindow(installer):
- bootloaders = [ _("Use Grand unified bootloader"), _("Install no bootloader"),]
- default = bootloaders[0] # first should a bootloader
-
- (button, choice) = ListboxChoiceWindow(installer.intf.screen,
- _("Bootloader"),
- _("Which bootloader do you want to install?\n\n"
- "NOTE: If you don't choose a bootloader the system "
- "might not be bootable!"),
- bootloaders, buttons = [TEXT_OK_BUTTON, TEXT_BACK_BUTTON],
- width = 60, default=default, height = len(bootloaders))
-
- if button == TEXT_BACK_CHECK:
- return INSTALL_BACK
-
- installer.log.info("User has chosen \"%s\"" % bootloaders[choice])
- # XXX skip step installbootloader here
-
- return INSTALL_OK