X-Git-Url: http://pere.pagekite.me/gitweb/homepage.git/blobdiff_plain/0ddcab0b9c191a0c84a7d95bf39192b8a37c7a52..f7c22ab984131ca652c0260c76ffff22398a2bae:/blog/index.html diff --git a/blog/index.html b/blog/index.html index 3036bf6fca..9ab7bd1c92 100644 --- a/blog/index.html +++ b/blog/index.html @@ -19,6 +19,240 @@ +
+
Testing if a file system can be used for home directories...
+
2010-08-08 21:20
+
+

A few years ago, I was involved in a project planning to use +Windows file servers as home directory servers for Debian +Edu/Skolelinux machines. This was thought to be no problem, as the +access would be through the SMB network file system protocol, and we +knew other sites used SMB with unix and samba as the file server to +mount home directories without any problems. But, after months of +struggling, we had to conclude that our goal was impossible.

+ +

The reason is simply that while SMB can be used for home +directories when the file server is Samba running on Unix, this only +work because of Samba have some extensions and the fact that the +underlying file system is a unix file system. When using a Windows +file server, the underlying file system do not have POSIX semantics, +and several programs will fail if the users home directory where they +want to store their configuration lack POSIX semantics.

+ +

As part of this work, I wrote a small C program I want to share +with you all, to replicate a few of the problematic applications (like +OpenOffice.org and GCompris) and see if the file system was working as +it should. If you find yourself in spooky file system land, it might +help you find your way out again. This is the fs-test.c source:

+ +
+/*
+ * Some tests to check the file system sematics.  Used to verify that
+ * CIFS from a windows server do not work properly as a linux home
+ * directory.
+ * License: GPL v2 or later
+ * 
+ * needs libsqlite3-dev and build-essential installed
+ * compile with: gcc -Wall -lsqlite3 -DTEST_SQLITE fs-test.c -o fs-test
+*/
+
+#define _FILE_OFFSET_BITS 64
+#define _LARGEFILE_SOURCE 1
+#define _LARGEFILE64_SOURCE 1
+
+#define _GNU_SOURCE /* for asprintf() */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifdef TEST_SQLITE
+/*
+ * Test sqlite open, as done by gcompris require the libsqlite3-dev
+ * package and linking with -lsqlite3.  A more low level test is
+ * below.
+ * See also .
+ */
+#include 
+#define CREATE_TABLE_USERS                                              \
+  "CREATE TABLE users (user_id INT UNIQUE, login TEXT, lastname TEXT, firstname TEXT, birthdate TEXT, class_id INT ); "
+int test_sqlite_open(void) {
+  char *zErrMsg;
+  char *name = "testsqlite.db";
+  sqlite3 *db=NULL;
+  unlink(name);
+  int rc = sqlite3_open(name, &db);
+  if( rc ){
+    printf("error: sqlite open of %s failed: %s\n", name, sqlite3_errmsg(db));
+    sqlite3_close(db);
+    return -1;
+  }
+
+  /* create tables */
+  rc = sqlite3_exec(db,CREATE_TABLE_USERS, NULL,  0, &zErrMsg);
+  if( rc != SQLITE_OK ){
+    printf("error: sqlite table create failed: %s\n", zErrMsg);
+    sqlite3_close(db);
+    return -1;
+  }
+  printf("info: sqlite worked\n");
+  sqlite3_close(db);
+  return 0;
+}
+#endif /* TEST_SQLITE */
+
+/*
+ * Demonstrate locking issue found in gcompris using sqlite3.  This
+ * work with ext3, but not with cifs server on Windows 2003.  This is
+ * done in the sqlite3 library.
+ * See also
+ *  and the
+ * POSIX specification
+ * .
+ */
+int test_gcompris_locking(void) {
+  struct flock fl;
+  char *name = "testsqlite.db";
+  unlink(name);
+  int fd = open(name, O_RDWR|O_CREAT|O_LARGEFILE, 0644);
+  printf("info: testing fcntl locking\n");
+
+  fl.l_whence = SEEK_SET;
+  fl.l_pid    = getpid();
+  printf("  Read-locking 1 byte from 1073741824");
+  fl.l_start  = 1073741824;
+  fl.l_len    = 1;
+  fl.l_type   = F_RDLCK;
+  if (0 != fcntl(fd, F_SETLK, &fl) ) printf(" - error!\n"); else printf("\n");
+
+  printf("  Read-locking 510 byte from 1073741826");
+  fl.l_start  = 1073741826;
+  fl.l_len    = 510;
+  fl.l_type   = F_RDLCK;
+  if (0 != fcntl(fd, F_SETLK, &fl) ) printf(" - error!\n"); else printf("\n");
+
+  printf("  Unlocking 1 byte from 1073741824");
+  fl.l_start  = 1073741824;
+  fl.l_len    = 1;
+  fl.l_type   = F_UNLCK;
+  if (0 != fcntl(fd, F_SETLK, &fl) ) printf(" - error!\n"); else printf("\n");
+
+  printf("  Write-locking 1 byte from 1073741824");
+  fl.l_start  = 1073741824;
+  fl.l_len    = 1;
+  fl.l_type   = F_WRLCK;
+  if (0 != fcntl(fd, F_SETLK, &fl) ) printf(" - error!\n"); else printf("\n");
+
+  printf("  Write-locking 510 byte from 1073741826");
+  fl.l_start  = 1073741826;
+  fl.l_len    = 510;
+  if (0 != fcntl(fd, F_SETLK, &fl) ) printf(" - error!\n"); else printf("\n");
+
+  printf("  Unlocking 2 byte from 1073741824");
+  fl.l_start  = 1073741824;
+  fl.l_len    = 2;
+  fl.l_type   = F_UNLCK;
+  if (0 != fcntl(fd, F_SETLK, &fl) ) printf(" - error!\n"); else printf("\n");
+
+  close(fd);
+  return 0;
+}
+
+/*
+ * Test if permissions of freshly created directories allow entries
+ * below them.  This was a problem with OpenOffice.org and gcompris.
+ * Mounting with option 'sync' seem to solve this problem while
+ * slowing down file operations.
+ */
+int test_subdirectory_creation(void) {
+#define LEVELS 5
+  char *path = strdup("test");
+  char *dirs[LEVELS];
+  int level;
+  printf("info: testing subdirectory creation\n");
+  for (level = 0; level < LEVELS; level++) {
+    char *newpath = NULL;
+    if (-1 == mkdir(path, 0777)) {
+      printf("  error: Unable to create directory '%s': %s\n",
+	     path, strerror(errno));
+      break;
+    }
+    asprintf(&newpath, "%s/%s", path, "test");
+    free(path);
+    path = newpath;
+  }
+  return 0;
+}
+
+/*
+ * Test if symlinks can be created.  This was a problem detected with
+ * KDE.
+ */
+int test_symlinks(void) {
+  printf("info: testing symlink creation\n");
+  unlink("symlink");
+  if (-1 == symlink("file", "symlink"))
+    printf("  error: Unable to create symlink\n");
+  return 0;
+}
+
+int main(int argc, char **argv) {
+  printf("Testing POSIX/Unix sematics on file system\n");
+  test_symlinks();
+  test_subdirectory_creation();
+#ifdef TEST_SQLITE
+  test_sqlite_open();
+#endif /* TEST_SQLITE */
+  test_gcompris_locking();
+  return 0;
+}
+
+ +

When everything is working, it should print something like +this:

+ +
+Testing POSIX/Unix sematics on file system
+info: testing symlink creation
+info: testing subdirectory creation
+info: sqlite worked
+info: testing fcntl locking
+  Read-locking 1 byte from 1073741824
+  Read-locking 510 byte from 1073741826
+  Unlocking 1 byte from 1073741824
+  Write-locking 1 byte from 1073741824
+  Write-locking 510 byte from 1073741826
+  Unlocking 2 byte from 1073741824
+
+ +

I do not remember the exact details of the problems we saw, but one +of them was with locking, where if I remember correctly, POSIX allow a +read-only lock to be upgraded to a read-write lock without unlocking +the read-only lock (while Windows do not). Another was a bug in the +CIFS/SMB client implementation in the Linux kernel where directory +meta information would be wrong for a fraction of a second, making +OpenOffice.org fail to create its deep directory tree because it was +not allowed to create files in its freshly created directory.

+ +

Anyway, here is a nice tool for your tool box, might you never need +it. :)

+
+
+ + + + Tags: debian edu, english, nuug. + +
+
+
+
Autodetecting Client setup for roaming workstations in Debian Edu
2010-08-07 14:45
@@ -830,95 +1064,6 @@ please contact us on debian-edu@lists.debian.org.

- Tags: debian, debian edu, english, ldap, nuug. - -
- -
- -
-
Idea for storing LTSP configuration in LDAP
-
2010-07-11 22:00
-
-

Vagrant mentioned on IRC today that ltsp_config now support -sourcing files from /usr/share/ltsp/ltsp_config.d/ on the thin -clients, and that this can be used to fetch configuration from LDAP if -Debian Edu choose to store configuration there.

- -

Armed with this information, I got inspired and wrote a test module -to get configuration from LDAP. The idea is to look up the MAC -address of the client in LDAP, and look for attributes on the form -ltspconfigsetting=value, and use this to export SETTING=value to the -LTSP clients.

- -

The goal is to be able to store the LTSP configuration attributes -in a "computer" LDAP object used by both DNS and DHCP, and thus -allowing us to store all information about a computer in one place.

- -

This is a untested draft implementation, and I welcome feedback on -this approach. A real LDAP schema for the ltspClientAux objectclass -need to be written. Comments, suggestions, etc?

- -
-# Store in /opt/ltsp/$arch/usr/share/ltsp/ltsp_config.d/ldap-config
-#
-# Fetch LTSP client settings from LDAP based on MAC address
-#
-# Uses ethernet address as stored in the dhcpHost objectclass using
-# the dhcpHWAddress attribute or ethernet address stored in the
-# ieee802Device objectclass with the macAddress attribute.
-#
-# This module is written to be schema agnostic, and only depend on the
-# existence of attribute names.
-#
-# The LTSP configuration variables are saved directly using a
-# ltspConfig prefix and uppercasing the rest of the attribute name.
-# To set the SERVER variable, set the ltspConfigServer attribute.
-#
-# Some LDAP schema should be created with all the relevant
-# configuration settings.  Something like this should work:
-# 
-# objectclass ( 1.1.2.2 NAME 'ltspClientAux'
-#     SUP top
-#     AUXILIARY
-#     MAY ( ltspConfigServer $ ltsConfigSound $ ... )
-
-LDAPSERVER=$(debian-edu-ldapserver)
-if [ "$LDAPSERVER" ] ; then
-    LDAPBASE=$(debian-edu-ldapserver -b)
-    for MAC in $(LANG=C ifconfig |grep -i hwaddr| awk '{print $5}'|sort -u) ; do
-	filter="(|(dhcpHWAddress=ethernet $MAC)(macAddress=$MAC))"
-	ldapsearch -h "$LDAPSERVER" -b "$LDAPBASE" -v -x "$filter" | \
-	    grep '^ltspConfig' | while read attr value ; do
-	    # Remove prefix and convert to upper case
-	    attr=$(echo $attr | sed 's/^ltspConfig//i' | tr a-z A-Z)
-	    # bass value on to clients
-	    eval "$attr=$value; export $attr"
-	done
-    done
-fi
-
- -

I'm not sure this shell construction will work, because I suspect -the while block might end up in a subshell causing the variables set -there to not show up in ltsp-config, but if that is the case I am sure -the code can be restructured to make sure the variables are passed on. -I expect that can be solved with some testing. :)

- -

If you want to help out with implementing this for Debian Edu, -please contact us on debian-edu@lists.debian.org.

- -

Update 2010-07-17: I am aware of another effort to store LTSP -configuration in LDAP that was created around year 2000 by -PC -Xperience, Inc., 2000. I found its -files on a -personal home page over at redhat.com.

-
-
- - - Tags: debian, debian edu, english, ldap, nuug.
@@ -953,7 +1098,7 @@ personal home page over at redhat.com.

  • July (12)
  • -
  • August (2)
  • +
  • August (3)
  • @@ -1012,9 +1157,9 @@ personal home page over at redhat.com.

  • debian (35)
  • -
  • debian edu (38)
  • +
  • debian edu (39)
  • -
  • english (53)
  • +
  • english (54)
  • fiksgatami (1)
  • @@ -1032,7 +1177,7 @@ personal home page over at redhat.com.

  • norsk (71)
  • -
  • nuug (90)
  • +
  • nuug (91)
  • opphavsrett (14)
  • @@ -1061,7 +1206,7 @@ personal home page over at redhat.com.

    -Created by Chronicle v3.2 +Created by Chronicle v3.7