summaryrefslogtreecommitdiff
path: root/src/caas/services/passwordservice.py
blob: ab666c879cbb02830671f5ea010e8293265bb145 (plain)
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
import csv
import hashlib
import os
from io import TextIOWrapper
from django.conf import settings
from ..models import Cluster, Server, Credential, Chassis, Blade, Vendor
import logging

logger = logging.getLogger("caas")

class PasswordService():
    @staticmethod
    def import_password_data(filehandle):
        f = TextIOWrapper(filehandle, encoding = "ascii", errors = "replace")
        csv_reader = csv.reader(f, delimiter=",")
        for row in csv_reader:
            serial_number_chassis = "ILO%s" % row[1]
            serial_number_blade = "ILO%s" % row[2]
            password = row[3]
            credential_kwargs = {"bmc_password_admin_default": password,
                                 "bmc_password_admin__isnull": True,
                                 "bmc_username__isnull": True,
                                 "bmc_password__isnull": True}
            credential, credential_created = Credential.objects.get_or_create(**credential_kwargs)
            chassis_kwargs = {"serial_number": serial_number_chassis}
            chassis, chassis_created = Chassis.objects.get_or_create(**chassis_kwargs)
            blade_kwargs = {"serial_number": serial_number_blade}
            blade, blade_created = Blade.objects.get_or_create(**blade_kwargs)
            blade.credential = credential
            blade.chassis = chassis
            credential.save()
            chassis.save()
            blade.save()

    @staticmethod
    def get_server_link_data(ilo_host_address):
        try:
            server_kwargs = {"ilo_host_address": ilo_host_address}
            server = Server.objects.get(**server_kwargs)
        except Server.DoesNotExist:
            logger.error("FAILED: while linking server to blade: failed to look up server ilo_host_address=%s" % ilo_host_address)
            return None
        try:
            blade_kwargs = {"id": server.blade.pk}
            blade = Blade.objects.get(**blade_kwargs)
        except Blade.DoesNotExist:
            logger.error("FAILED: while linking server to blade: failed to look up blade ilo_host_address=%s" % ilo_host_address)
            return None
        try:
            vendor_kwargs = {"id": blade.vendor.pk}
            vendor = Vendor.objects.get(**vendor_kwargs)
        except Vendor.DoesNotExist:
            logger.error("FAILED: while linking server to blade: failed to look up vendor ilo_host_address=%s" % ilo_host_address)
            return None
        return {"vendor": vendor.vendor_name,
                "serial_number": blade.serial_number,
                "ilo_host_address": server.ilo_host_address}

    @staticmethod
    def link_server_to_blade(vendor_name, serial_number, ilo_host_address):
        try:
            server_kwargs = {"ilo_host_address": ilo_host_address}
            server = Server.objects.get(**server_kwargs)
        except Server.DoesNotExist:
            logger.error("FAILED: while linking server to blade: failed to look up server! ilo_host_address=%s" % ilo_host_address)
            return None
        try:
            blade_kwargs = {"serial_number": serial_number}
            blade = Blade.objects.get(**blade_kwargs)
        except Blade.DoesNotExist:
            logger.error("FAILED: while linking server to blade: failed to look up blade! ilo_host_address=%s" % ilo_host_address)
            return None
        try:
            vendor_kwargs = {"vendor_name": vendor_name}
            vendor = Vendor.objects.get(**vendor_kwargs)
        except Vendor.DoesNotExist:
            logger.error("FAILED: while linking server to blade: failed to look up vendor! ilo_host_address=%s" % ilo_host_address)
            return None
        server.blade = blade
        blade.vendor = vendor
        server.save()
        blade.save()
        return server

    @staticmethod
    def is_server_linked_to_blade(ilo_host_address):
        try:
            server_kwargs = {"ilo_host_address": ilo_host_address}
            server = Server.objects.get(**server_kwargs)
        except Server.DoesNotExist:
            return True     # server doesn't exist, no action should be triggered

        if server.blade is None or server.pxe_mac_address is None:
            return False   # server is not yet linked with blade
        else:
            return True    # server is already linked with blade

    @staticmethod
    def generate_unique_password():
        m = hashlib.sha1()
        m.update(os.urandom(16))
        return m.hexdigest()[:20]

    @staticmethod
    def create_bmc_admin_password(serial_number):
        try:
            blade_kwargs = {"serial_number": serial_number}
            blade = Blade.objects.get(**blade_kwargs)
        except Blade.DoesNotExist:
            logger.error("FAILED: while creating BMC account: failed to look up blade for serial %s" % serial_number)
            return -1
        if blade.credential is None:
            logger.error("FAILED: while creating BMC account: failed to look up credential for serial %s" % serial_number)
            return -1
        if blade.credential.bmc_password is None:
            # We don't want to update this Credential because it will affect
            # every Blade that is tied to it. We need to create a new
            # Credential and link the Blade to the new Credential.
            admin_password = PasswordService.generate_unique_password()
            ospctl_password = PasswordService.generate_unique_password()
            credential_kwargs = {"bmc_password_admin_default": blade.credential.bmc_password_admin_default}
            credential, credential_created = Credential.objects.get_or_create(**credential_kwargs)
            blade.credential = credential
            credential.bmc_password_admin = admin_password
            credential.bmc_username = settings.BMC_USERNAME
            credential.bmc_password = ospctl_password
            blade.save()
            credential.save()
            logger.debug("OK: passwords created for serial %s" % serial_number)
            return 0
        logger.debug("OK: no-op for serial %s" % serial_number)
        return 0

    @staticmethod
    def central_server_p(ilo_host_address):
        try:
            server_kwargs = {"ilo_host_address": ilo_host_address}
            server = Server.objects.get(**server_kwargs)
        except Server.DoesNotExist:
            logger.error("FAILED: while determining if the server with ilo_host_address %s is a central server: server not found." % ilo_host_address)
            return True
        try:
            cluster_kwargs = {"id": server.cluster.pk}
            cluster = Cluster.objects.get(**cluster_kwargs)
        except Cluster.DoesNotExist:
            logger.error("FAILED: while determining if the server with ilo_host_address %s is a central server: cluster not found." % ilo_host_address)
            return True
        return False if cluster.is_central_controller==0 else True

    @staticmethod
    def fix_creds():
        bad_creds = Credential.objects.raw("""
with dupes (bmc_password_admin_default, zahl) as (
    select bmc_password_admin_default,
        count(bmc_password_admin_default) as zahl
    from caas_credential
    group by bmc_password_admin_default
)
select c.id,
    c.bmc_password_admin_default,
    c.bmc_password_admin,
    c.bmc_username,
    c.bmc_password
from caas_credential c
left outer join dupes d
    on c.bmc_password_admin_default = d.bmc_password_admin_default
where d.zahl > 1
    and bmc_password is null""")
        for bad_cred in bad_creds:
            good_cred_kwargs = {"bmc_password_admin_default": bad_cred.bmc_password_admin_default,
                                "bmc_password__isnull": False}
            good_cred = Credential.objects.get(**good_cred_kwargs)
            try:
                blade_kwargs = {"credential_id": bad_cred.id}
                blade = Blade.objects.get(**blade_kwargs)
                blade.credential_id = good_cred.pk
                blade.save()
                bad_cred.delete()
            except Blade.DoesNotExist:
                pass