1#!/usr/bin/env python3
2
3import json
4import os
5import re
6from collections import OrderedDict
7
8from data import variables
9
10bmc_rec_pattern = "^=(.*)\n(.*)\n(.*)\n(.*)\n(.*)"
11bmc_prop_pattern = [r"\w+", r"\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}", "443"]
12bmc_rec_prop = ["hostname", "address", "port", "txt"]
13
14
15class Exception(Exception):
16    def __init__(self, exc_value):
17        self.exc_value = exc_value
18
19    def __str__(self):
20        return repr(self.exc_value)
21
22
23def Check_bmc_record_exists(bmc_records, bmc_ip):
24    r"""
25    Parse the BMC records to check for passed input.
26
27    Description of arguments:
28    bmc_records            Contains the list of discoverd BMC records.
29    bmc_ip                 BMC ip address.
30    """
31
32    try:
33        for bmc_key, bmc_val in bmc_records.items():
34            temp_ip = bmc_val.get("address", None)
35            if bmc_ip.strip() == temp_ip.strip():
36                return True
37        else:
38            return False
39    except Exception as exc_obj:
40        return exc_obj
41
42
43def validate_bmc_properties(
44    bmc_prop_pattern, bmc_prop, bmc_value, bmc_rec_valid
45):
46    r"""
47    This function is to check pattern match in bmc properties.
48
49    Description of arguments:
50    bmc_prop_pattern       Regex pattern.
51    bmc_prop               BMC property (e.g. hostname, address, port).
52    bmc_value              BMC property value.
53    bmc_rec_valid          Contain BMC properties record.
54    """
55
56    try:
57        status = [
58            lambda bmc_prop: re.search(bmc_prop_pattern, bmc_prob),
59            bmc_value,
60        ]
61        if None in status:
62            bmc_rec_valid[bmc_prop] = None
63    except Exception as exc_obj:
64        return exc_obj
65    finally:
66        return bmc_rec_valid
67
68
69def bmc_record_validation(bmc_rec_valid):
70    r"""
71    Parse the BMC records to validate the data is valid.
72
73    Description of arguments:
74    bmc_rec_valid          Contain BMC properties record.
75    """
76
77    try:
78        for bmc_prop_key, bmc_pattern_val in zip(
79            bmc_rec_prop, bmc_prop_pattern
80        ):
81            bmc_prop_value = bmc_rec_valid.get(bmc_prop_key, False)
82            if bmc_rec_valid[bmc_prop_key] is not False:
83                valid_status = validate_bmc_properties(
84                    bmc_pattern_val,
85                    bmc_prop_key,
86                    bmc_prop_value,
87                    bmc_rec_valid,
88                )
89                if None not in bmc_rec_valid.values():
90                    return bmc_rec_valid
91                else:
92                    return None
93    except Exception as exc_obj:
94        return exc_obj
95
96
97def bmc_inventory(service_type, bmc_inv_record):
98    r"""
99    Parse single record of BMC inventory and pack to dictionary form.
100
101    Description of arguments:
102    service_type       Service type (e.g. _obmc_rest._tcp, _obmc_redfish._tcp).
103    bmc_inv_record     Individual BMC inventory record.
104
105    This function will return this variable i.e.
106    bmc_inv in dictionary form as mention below.
107
108    Below are the discovered BMC detail.
109
110    [service]:          _obmc_XXXX._tcp
111    [hostname]:         System Name
112    [address]:          XXX.XXX.XXX.XXX
113    [port]:             XXX
114    [txt]:
115    """
116
117    try:
118        exc_obj = None
119        bmc_inv = OrderedDict()
120        service_count = 0
121        for line in bmc_inv_record.split("\n"):
122            if line == "":
123                pass
124            elif service_type in line:
125                bmc_inv["service"] = service_type
126                service_count += 1
127            elif not line.startswith("=") and service_count == 1:
128                bmc_inv[line.split("=")[0].strip()] = str(
129                    line.split("=")[-1].strip()
130                )[1:-1]
131    except Exception as exc_obj:
132        return exc_obj
133    finally:
134        valid_status = bmc_record_validation(bmc_inv)
135        if valid_status is None:
136            return None, exc_obj
137        else:
138            return valid_status, exc_obj
139
140
141def get_bmc_records(service_type, bmc_records):
142    r"""
143    Parse the string to filter BMC discovery.
144
145    Description of arguments:
146    service_type     Service type (e.g. RESTService, RedfishService).
147    bmc_records      Contains the list of discoverd BMC records.
148
149    This function will return this variable i.e.
150    bmc_inv_list in dictionary form as mention below.
151
152    Below are the list of discovered BMC details.
153    [1]:
154        [service]:          _obmc_XXXX._tcp
155        [hostname]:         System Name
156        [address]:          XXX.XXX.XXX.XXX
157        [port]:             XXX
158        [txt]:
159    [2]:
160        [service]:          _obmc_XXXX._tcp
161        [hostname]:         System Name
162        [address]:          XXX.XXX.XXX.XXX
163        [port]:             XXX
164        [txt]:
165    """
166
167    try:
168        count = 0
169        exe_obj = None
170        bmc_inv_list = OrderedDict()
171        for match in re.finditer(bmc_rec_pattern, bmc_records, re.MULTILINE):
172            bmc_record, exc_msg = bmc_inventory(service_type, match.group())
173            if bmc_record is not None and exc_msg is None:
174                count += 1
175                bmc_inv_list[count] = bmc_record
176    except Exception as exe_obj:
177        return exe_obj
178    finally:
179        if len(bmc_inv_list) == 0:
180            "", exe_obj
181        else:
182            return bmc_inv_list, exe_obj
183