Revision a442c81d snf-cyclades-app/synnefo/logic/management/commands/cyclades-astakos-migrate-013.py

b/snf-cyclades-app/synnefo/logic/management/commands/cyclades-astakos-migrate-013.py
32 32
# or implied, of GRNET S.A.
33 33

  
34 34
import itertools
35
import warnings
36 35
import functools
37 36

  
38 37
from optparse import make_option
39 38

  
40
from django.core.management.base import NoArgsCommand, CommandError, BaseCommand
39
from django.core.management.base import CommandError, BaseCommand
41 40
from django.db import transaction
42 41
from django.conf import settings
43 42

  
......
48 47

  
49 48
from snf_django.lib import astakos
50 49

  
51
def warn(*msgs):
52
    print "WARNING: %s" % ' '.join(msgs)
53 50

  
54
get_displayname = functools.partial(astakos.get_displayname,
55
                                 settings.CYCLADES_SERVICE_TOKEN,
56
                                 url=settings.ASTAKOS_URL.replace('im/authenticate',
57
                                                                 'service/api/user_catalogs'))
58
get_user_uuid = functools.partial(astakos.get_user_uuid,
59
                                 settings.CYCLADES_SERVICE_TOKEN,
60
                                 url=settings.ASTAKOS_URL.replace('im/authenticate',
61
                                                                 'service/api/user_catalogs'))
62

  
63
def _validate_db_state(usernames):
64

  
65
    usernames = filter(bool, usernames)
66
    invalid_case_users = case_unique(usernames)
67
    if invalid_case_users:
68
        invalid_case_users.append(invalid_case_users[0].lower())
69
        raise CommandError("Duplicate case insensitive user identifiers exist %r" % invalid_case_users)
70

  
71
    uuidusers = filter(lambda uid:'@' in uid or uid == None, usernames)
72
    if len(uuidusers) != len(usernames):
73
        warn('It seems that mixed uuid/email user identifiers exist in database.')
74
        return False
75

  
76
    return True
77

  
78

  
79
@transaction.commit_manually
80
def delete_user(username, only_stats=True, dry=True):
81
    vms = VirtualMachine.objects.filter(userid__exact=username)
82
    networks = Network.objects.filter(userid__exact=username)
83
    keys = PublicKeyPair.objects.filter(user__exact=username)
84

  
85
    if not len(list(itertools.ifilter(bool, map(lambda q: q.count(), [vms,
86
                                                                      networks,
87
                                                                      keys])))):
88
        print "No entries exist for '%s'" % username
89
        return -1
90

  
91
    if only_stats:
92
        print "The following entries will be deleted if you decide to remove this user"
93
        print "%d Virtual Machines" % vms.exclude(operstate='DESTROYED').count()
94
        print "%d Destroyed Virtual Machines" % vms.filter(operstate='DESTROYED').count()
95
        print "%d Networks" % networks.count()
96
        print "%d PublicKeyPairs" % keys.count()
97
        return
98

  
99
    for o in itertools.chain(vms, networks):
100
        o.delete()
101

  
102
    for key in keys:
103
        key.delete()
104

  
105
    if dry:
106
        print "Skipping database commit."
107
        transaction.rollback()
108
    else:
109
        transaction.commit()
110
        print "User entries removed."
51
get_displayname = functools.partial(
52
    astakos.get_displayname, settings.CYCLADES_SERVICE_TOKEN,
53
    url=settings.ASTAKOS_URL.replace('im/authenticate',
54
                                     'service/api/user_catalogs'))
55
get_user_uuid = functools.partial(
56
    astakos.get_user_uuid, settings.CYCLADES_SERVICE_TOKEN,
57
    url=settings.ASTAKOS_URL.replace('im/authenticate',
58
                                     'service/api/user_catalogs'))
111 59

  
112 60

  
113 61
@transaction.commit_on_success
......
142 90
        key.save()
143 91

  
144 92

  
145
@transaction.commit_manually
146
def migrate_users(usernames, dry=True):
147
    usernames = filter(bool, usernames)
148
    count = 0
149
    for u in usernames:
150
        if not '@' in u:
151
            warn('Skipping %s. It doesn\'t seem to be an email' % u)
152
            continue
153

  
154
        try:
155
            uuid = get_user_uuid(u)
156
            print "%s -> %s" % (u, uuid)
157
            if not uuid:
158
                raise Exception("No uuid for %s" % u)
159
            migrate_user(u, uuid)
160
            count += 1
161
        except Exception, e:
162
            print "ERROR: User id migration failed (%s)" % e
163

  
164
    if dry:
165
        print "Skipping database commit."
166
        transaction.rollback()
167
    else:
168
        transaction.commit()
169
        print "Migrated %d users" % count
170

  
171

  
172
class Command(NoArgsCommand):
93
class Command(BaseCommand):
173 94
    help = "Quotas migration helper"
174 95

  
175 96
    option_list = BaseCommand.option_list + (
......
231 152
        if options.get('validate') and not options.get('merge_user') and not \
232 153
                options.get('delete_user') and not options.get('user_entries'):
233 154
            usernames = get_existing_users()
234
            _validate_db_state(usernames)
155
            self._validate_db_state(usernames)
235 156

  
236 157
        if options.get('migrate_users'):
237
            migrate_users(usernames, dry=self.dry)
158
            self.migrate_users(usernames, dry=self.dry)
238 159

  
239 160
        if options.get('merge_user'):
240 161
            merge_user(options.get('merge_user'))
241
            print "Merge finished."
162
            self.stderr.write("Merge finished.")
242 163

  
243 164
        if options.get('delete_user'):
244
            entries = delete_user(options.get('delete_user'), only_stats=True)
165
            entries = self.delete_user(options.get('delete_user'),
166
                                       only_stats=True)
245 167
            if entries == -1:
246 168
                return
247 169

  
......
250 172
            if not confirm == 'yes of course':
251 173
                return
252 174
            else:
253
                delete_user(options.get('delete_user'), only_stats=False,
254
                            dry=self.dry)
175
                self.delete_user(options.get('delete_user'), only_stats=False,
176
                                 dry=self.dry)
255 177

  
256 178
        if options.get('user_entries'):
257
            delete_user(options.get('user_entries'))
179
            self.delete_user(options.get('user_entries'))
180

  
181
    @transaction.commit_manually
182
    def delete_user(self, username, only_stats=True, dry=True):
183
        vms = VirtualMachine.objects.filter(userid__exact=username)
184
        networks = Network.objects.filter(userid__exact=username)
185
        keys = PublicKeyPair.objects.filter(user__exact=username)
186

  
187
        if not len(list(itertools.ifilter(bool,
188
                                          map(lambda q: q.count(),
189
                                              [vms, networks, keys])))):
190
            self.stderr.write("No entries exist for '%s'" % username)
191
            return -1
192

  
193
        if only_stats:
194
            self.stderr.write("The following entries will be deleted if "
195
                              "you decide to remove this user")
196
            self.stderr.write("%d Virtual Machines"
197
                              % vms.exclude(operstate='DESTROYED').count())
198
            self.stderr.write("%d Destroyed Virtual Machines"
199
                              % vms.filter(operstate='DESTROYED').count())
200
            self.stderr.write("%d Networks" % networks.count())
201
            self.stderr.write("%d PublicKeyPairs" % keys.count())
202
            return
203

  
204
        for o in itertools.chain(vms, networks):
205
            o.delete()
206

  
207
        for key in keys:
208
            key.delete()
209

  
210
        if dry:
211
            self.stderr.write("Skipping database commit.")
212
            transaction.rollback()
213
        else:
214
            transaction.commit()
215
            self.stderr.write("User entries removed.")
216

  
217
    def warn(self, *msgs):
218
        self.stderr.write("WARNING: %s" % ' '.join(msgs))
219

  
220
    def _validate_db_state(self, usernames):
221

  
222
        usernames = filter(bool, usernames)
223
        invalid_case_users = case_unique(usernames)
224
        if invalid_case_users:
225
            invalid_case_users.append(invalid_case_users[0].lower())
226
            raise CommandError(
227
                "Duplicate case insensitive user identifiers exist %r"
228
                % invalid_case_users)
229

  
230
        uuidusers = filter(lambda uid: '@' in uid or uid is None, usernames)
231
        if len(uuidusers) != len(usernames):
232
            self.warn("It seems that mixed uuid/email user "
233
                      "identifiers exist in database.")
234
            return False
235

  
236
        return True
237

  
238
    @transaction.commit_manually
239
    def migrate_users(self, usernames, dry=True):
240
        usernames = filter(bool, usernames)
241
        count = 0
242
        for u in usernames:
243
            if not '@' in u:
244
                self.warn('Skipping %s. It doesn\'t seem to be an email' % u)
245
                continue
246

  
247
            try:
248
                uuid = get_user_uuid(u)
249
                self.stderr.write("%s -> %s" % (u, uuid))
250
                if not uuid:
251
                    raise Exception("No uuid for %s" % u)
252
                migrate_user(u, uuid)
253
                count += 1
254
            except Exception, e:
255
                self.stderr.write("ERROR: User id migration failed (%s)" % e)
256

  
257
        if dry:
258
            self.stderr.write("Skipping database commit.")
259
            transaction.rollback()
260
        else:
261
            transaction.commit()
262
            self.stderr.write("Migrated %d users" % count)

Also available in: Unified diff