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