Ok, my bulk import users script now works as per my example above. I've just used it to import ~200 users from Zentyal 2.2 into Zentyal 3.2 and I successfully imported the unix uid (LDAP uidNumber) which had not been working.
How did I do this? Well, read on...
I spent a while crawling over the perl modules in /usr/share/perl5/EBox... and discovered an unexpeced behaviour. Maybe it's documented somewhere, but I haven't seen it. What happens when you call EBox::Users::User::create(...) is that a basic user is created with the absolute minimum of information. Then zentyal builds a list of the remaining ldap attributes to be set *BUT* before it actually writes it to the ldap db, it calls a special function called 'preAddUser' on a number of other EBox modules that have an interest in users. Exactly which of these gets called depends on which modules you have installed. This means that each of these preAddUser functions gets the chance to override any of the ldap attributes. In my case, the EBox::SambaLdapUser module was trying to be clever (too clever, IMHO). It was overriding the uidNumber supplied by my script with the Samba xidNumber (extended uid) attribute. As far as I can tell, these two items don't need to be the same, so I don't think EBox::SambaLdapUser should be overriding it. Anyway, that's not for me to say.
So, I reinstalled Zentyal 3.2 with only minimum modules and definitely no File Sharing (Samba), imported my users, and then installed and enabled File Sharing. So far all seems to be working well.
Here is the script I used to dump data from Zentyal 2.2 and generate a random pronounceable password for each user:
#!/usr/bin/perl
use strict;
use warnings;
use EBox;
use EBox::Global;
use Text::Password::Pronounceable;
EBox::init();
sub escape_text {
my ($txt) = @_;
$txt =~ s/:/_+_/;
return $txt;
}
my $usersMod = EBox::Global->modInstance('users');
my $users = $usersMod->usersList();
foreach my $user (@$users) {
my $detail = $usersMod->userInfo($user->{'user'});
my $email = $detail->{givenname} . "." . $detail->{surname} . '@somedomain.com';
$email =~ tr/A-Z/a-z/;
print join ":", escape_text($detail->{username}), Text::Password::Pronounceable->generate(8,10),
escape_text($detail->{uid}), escape_text($detail->{group}), escape_text($detail->{givenname}),
escape_text($detail->{surname}), escape_text($detail->{fullname}), $email;
print "\n";
}
1;
and the script to bulk import into 3.2:
#!/usr/bin/perl
use strict;
use warnings;
use EBox;
use EBox::Users::User;
use Data::Dumper;
EBox::init();
my $parent = EBox::Users::User->defaultContainer(1);
while (<>) {
chomp;
my ($username, $password, $uid, $gid, $first, $last, $full, $email) = split(':');
my $userObj = EBox::Users::User->create(
uid => $username,
password => $password,
uidNumber => $uid,
fullname => $full,
givenname => $first,
surname => $last,
description => 'Auto imported',
mail => $email,
parent => $parent
);
}
1;
Hope this is of some use to folks trying to do something similar to me.
-Bob