Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

# vim: tabstop=4 shiftwidth=4 softtabstop=4 

 

# Copyright 2012 OpenStack LLC 

# 

# Licensed under the Apache License, Version 2.0 (the "License"); you may 

# not use this file except in compliance with the License. You may obtain 

# a copy of the License at 

# 

#      http://www.apache.org/licenses/LICENSE-2.0 

# 

# Unless required by applicable law or agreed to in writing, software 

# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 

# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 

# License for the specific language governing permissions and limitations 

# under the License. 

 

import re 

 

import sqlalchemy 

from sqlalchemy import exc 

 

from keystone.common import logging 

from keystone import config 

from keystone.contrib.ec2.backends import sql as ec2_sql 

from keystone.identity.backends import sql as identity_sql 

 

 

LOG = logging.getLogger(__name__) 

CONF = config.CONF 

DEFAULT_DOMAIN_ID = CONF.identity.default_domain_id 

 

 

def export_db(db): 

    table_names = db.table_names() 

 

    migration_data = {} 

    for table_name in table_names: 

        query = db.execute("select * from %s" % table_name) 

        table_data = [] 

        for row in query.fetchall(): 

            entry = {} 

            for k in row.keys(): 

                entry[k] = row[k] 

            table_data.append(entry) 

 

        migration_data[table_name] = table_data 

 

    return migration_data 

 

 

def _translate_replacements(s): 

    if '%' not in str(s): 

        return s 

    return re.sub(r'%([\w_]+)%', r'$(\1)s', s) 

 

 

class LegacyMigration(object): 

    def __init__(self, db_string): 

        self.db = sqlalchemy.create_engine(db_string) 

        self.identity_driver = identity_sql.Identity() 

        self.identity_driver.db_sync() 

        self.ec2_driver = ec2_sql.Ec2() 

        self._data = {} 

        self._user_map = {} 

        self._project_map = {} 

        self._role_map = {} 

 

    def migrate_all(self): 

        self._export_legacy_db() 

        self._migrate_projects() 

        self._migrate_users() 

        self._migrate_roles() 

        self._migrate_user_roles() 

        self._migrate_tokens() 

        self._migrate_ec2() 

 

    def dump_catalog(self): 

        """Generate the contents of a catalog templates file.""" 

        self._export_legacy_db() 

 

        services_by_id = dict((x['id'], x) for x in self._data['services']) 

        template = 'catalog.%(region)s.%(service_type)s.%(key)s = %(value)s' 

 

        o = [] 

        for row in self._data['endpoint_templates']: 

            service = services_by_id[row['service_id']] 

            d = {'service_type': service['type'], 

                 'region': row['region']} 

 

            for x in ['internal_url', 'public_url', 'admin_url', 'enabled']: 

                d['key'] = x.replace('_url', 'URL') 

                d['value'] = _translate_replacements(row[x]) 

                o.append(template % d) 

 

            d['key'] = 'name' 

            d['value'] = service['desc'] 

            o.append(template % d) 

 

        return o 

 

    def _export_legacy_db(self): 

        self._data = export_db(self.db) 

 

    def _migrate_projects(self): 

        for x in self._data['tenants']: 

            # map 

            new_dict = {'description': x.get('desc', ''), 

                        'id': x.get('uid', x.get('id')), 

                        'enabled': x.get('enabled', True), 

                        'domain_id': x.get('domain_id', DEFAULT_DOMAIN_ID)} 

            new_dict['name'] = x.get('name', new_dict.get('id')) 

            # track internal ids 

            self._project_map[x.get('id')] = new_dict['id'] 

            # create 

            #print 'create_project(%s, %s)' % (new_dict['id'], new_dict) 

            self.identity_driver.create_project(new_dict['id'], new_dict) 

 

    def _migrate_users(self): 

        for x in self._data['users']: 

            # map 

            new_dict = {'email': x.get('email', ''), 

                        'password': x.get('password', None), 

                        'id': x.get('uid', x.get('id')), 

                        'enabled': x.get('enabled', True), 

                        'domain_id': x.get('domain_id', DEFAULT_DOMAIN_ID)} 

127            if x.get('tenant_id'): 

                new_dict['tenant_id'] = self._project_map.get(x['tenant_id']) 

            new_dict['name'] = x.get('name', new_dict.get('id')) 

            # track internal ids 

            self._user_map[x.get('id')] = new_dict['id'] 

            # create 

            #print 'create_user(%s, %s)' % (new_dict['id'], new_dict) 

            self.identity_driver.create_user(new_dict['id'], new_dict) 

135            if new_dict.get('tenant_id'): 

                self.identity_driver.add_user_to_project( 

                    new_dict['tenant_id'], 

                    new_dict['id']) 

 

    def _migrate_roles(self): 

        for x in self._data['roles']: 

            # map 

            new_dict = {'id': x['id'], 

                        'name': x.get('name', x['id'])} 

            # track internal ids 

            self._role_map[x.get('id')] = new_dict['id'] 

            # create 

            self.identity_driver.create_role(new_dict['id'], new_dict) 

 

    def _migrate_user_roles(self): 

        for x in self._data['user_roles']: 

            # map 

155            if (not x.get('user_id') 

                    or not x.get('tenant_id') 

                    or not x.get('role_id')): 

                continue 

            user_id = self._user_map[x['user_id']] 

            tenant_id = self._project_map[x['tenant_id']] 

            role_id = self._role_map[x['role_id']] 

 

            try: 

                self.identity_driver.add_user_to_project(tenant_id, user_id) 

            except Exception: 

                pass 

 

            self.identity_driver.add_role_to_user_and_project( 

                user_id, tenant_id, role_id) 

 

    def _migrate_tokens(self): 

        pass 

 

    def _migrate_ec2(self): 

        for x in self._data['credentials']: 

            new_dict = {'user_id': x['user_id'], 

                        'tenant_id': x['tenant_id'], 

                        'access': x['key'], 

                        'secret': x['secret']} 

            try: 

                self.ec2_driver.create_credential(None, new_dict) 

            except exc.IntegrityError: 

                LOG.exception(_('Cannot migrate EC2 credential: %s') % x)