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