summaryrefslogtreecommitdiff
path: root/src/caas/services/ciqservice.py
blob: a97e9e0b6023cf27ac8d9c249dc602c6da5ee752 (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
181
182
183
184
185
186
187
188
189
190
191
192
193
import csv
import ipaddress
from io import TextIOWrapper
from django.db import connections
from django.conf import settings
from .helpers import Address, RawQuery
from ..models import Vlan, Namespace, CellSiteRouter, SapClli, Location, Cluster, Server


"""
Derive IPs from rules defined in the LLD:
https://oneconfluence.verizon.com/display/NTD/VRAN+2.0+Far+Edge?preview=/554294908/592448982/vRAN%202.0%20on%20VCP%20Far%20Edge_WebScale%20Transport%20LLD%20v2.3.pdf
"""
class CiqService():
    @staticmethod
    def import_ciq_data(filehandle, assign_parent = False):
        with connections["default"].cursor() as cursor:
            f = TextIOWrapper(filehandle, encoding = "ascii", errors = "replace")
            csv_reader = csv.reader(f, delimiter = ",")
            for row in csv_reader:
                # Fetch data from CSV row
                fuze_spm_site_id = row[1]
                fuze_spm_site_name = row[3]
                fuze_spm_market = row[4]
                fuze_spm_submarket = row[5]
                fuze_spm_site_type = row[6]
                central_controller_sap_clli = row[7]
                server_number = int(row[9])
                ilo_hostname = row[10].lower()
                cluster_name = row[11].lower()
                namespace_name = row[12].lower()
                host_vlan = int(row[13])
                oam_vlan = int(row[14])
                mgmt_vlan = int(row[15])
                csr_hostname = row[17]
                ilo_host_address = ipaddress.IPv6Address(row[23])
                ilo_default_gateway = ipaddress.IPv6Address(row[24])
                mgmt_default_gateway = ipaddress.IPv6Address(row[25])
                oam_default_gateway = ipaddress.IPv6Address(row[26])
                central_controller_p = bool(row[28])

                # Use the minimum uniquely identifying data to load existing matching records if available

                # location
                location_kwargs = {"fuze_spm_site_id": fuze_spm_site_id}
                location, location_created = Location.objects.get_or_create(**location_kwargs)
                location.fuze_spm_site_name = fuze_spm_site_name
                location.fuze_spm_market = fuze_spm_market
                location.fuze_spm_submarket = fuze_spm_submarket
                location.fuze_spm_site_type = fuze_spm_site_type

                # vlan
                vlan_kwargs = {"host_vlan": host_vlan,
                               "oam_vlan": oam_vlan,
                               "mgmt_vlan": mgmt_vlan}
                vlan, vlan_created = Vlan.objects.get_or_create(**vlan_kwargs)

                # csr
                csr_kwargs = {"csr_hostname": csr_hostname}
                csr, csr_created = CellSiteRouter.objects.get_or_create(**csr_kwargs)

                # sap_clli
                sap_clli_kwargs = {"clli": central_controller_sap_clli}
                sap_clli, sap_clli_created = SapClli.objects.get_or_create(**sap_clli_kwargs)

                # cluster
                cluster_kwargs = {"cluster_name": cluster_name}
                cluster, cluster_created = Cluster.objects.get_or_create(**cluster_kwargs)

                # namespaces
                namespace_kwargs = {"namespace_name": namespace_name}
                namespace, namespace_created = Namespace.objects.get_or_create(**namespace_kwargs)

                # server
                server_kwargs = {"ilo_hostname": ilo_hostname}
                server, server_created = Server.objects.get_or_create(**server_kwargs)

                parent_cluster = None

                if not central_controller_p:
                    # find least-used parent central controller cluster
                    parent_clusters_kwargs = {"sap_clli_id__exact": sap_clli.pk,
                                              "parent_cluster_id__isnull": True,
                                              "is_central_controller": 1}
                    parent_clusters = Cluster.objects.filter(**parent_clusters_kwargs)
                    subcloud_counts = {}

                    for parent in parent_clusters:
                        num_children = RawQuery.query_single_value(cursor, """
select count(*) as num_children
from caas_cluster
where parent_cluster_id = %s and is_central_controller = 0""" % parent.pk, "num_children")

                        if num_children < settings.WR_MAX_CHILD_CLUSTERS:
                            subcloud_counts[parent.pk] = [num_children, parent]

                    if len(subcloud_counts) != 0:
                        parent_cluster = min(subcloud_counts.items(), key=lambda x: x[1][0])[1][1]

                    # Derive subnets from gateways
                    oam_subnet = Address.add_40a(Address.gateway_to_subnet(oam_default_gateway))
                    mgmt_subnet = Address.add_40a(Address.gateway_to_subnet(mgmt_default_gateway))
                    ilo_subnet = Address.add_40a(Address.gateway_to_subnet(ilo_default_gateway))

                    # oam vip
                    need_ip = False

                    if csr.oam_subnet == str(oam_subnet) and csr.oam_default_gateway == str(oam_default_gateway):
                        if cluster.oam_vip_address is None:
                            need_ip = True
                    else:
                        csr.oam_subnet = str(oam_subnet)
                        csr.oam_default_gateway = str(oam_default_gateway)
                        need_ip = True
                    if need_ip:
                        oam_vip_address_max = RawQuery.query_single_value(cursor, """
with oam_ips as (
    select csr.id as csr_id,
        c.oam_vip_address
    from caas_server s
    inner join caas_cluster c
        on s.cluster_id = c.id
    inner join caas_cellsiterouter csr
        on c.csr_id = csr.id
)
select max(oam_vip_address) as max
from oam_ips
where csr_id = %s""" % csr.id, "max")
                        if oam_vip_address_max:
                            oam_vip_address_max = str(Address.next_address(oam_vip_address_max, oam_subnet, 0x10))
                        else:
                            oam_vip_address_max = str(Address.next_address(oam_vip_address_max, oam_subnet, 0xf400))
                        cluster.oam_vip_address = oam_vip_address_max
                    # oam host
                    need_ip = False
                    if csr.oam_subnet == str(oam_subnet) and csr.oam_default_gateway == str(oam_default_gateway):
                        if server.oam_host_address is None:
                            need_ip = True
                    else:
                        csr.oam_subnet = str(oam_subnet)
                        csr.oam_default_gateway = str(oam_default_gateway)
                        need_ip = True
                    if need_ip:
                        oam_host_address_max = RawQuery.query_single_value(cursor, """
with oam_ips as (
    select csr.id as csr_id,
        s.oam_host_address
    from caas_server s
    inner join caas_cluster c
        on s.cluster_id = c.id
    inner join caas_cellsiterouter csr
        on c.csr_id = csr.id
)
select max(oam_host_address) as max
from oam_ips
where csr_id = %s""" % csr.id, "max")
                        if oam_host_address_max:
                            oam_host_address_max = str(Address.next_address(oam_host_address_max, oam_subnet, 0x1))
                        else:
                            oam_host_address_max = str(Address.next_address(oam_host_address_max, oam_subnet, 0x400))
                        server.oam_host_address = oam_host_address_max

                    # mgmt
                    cluster.mgmt_subnet = str(mgmt_subnet)
                    cluster.mgmt_default_gateway = str(mgmt_default_gateway)
                    cluster.mgmt_address_range_start = str(mgmt_subnet)
                    cluster.mgmt_address_range_end = str(Address.address_add(cluster.mgmt_address_range_start, 0xf))

                    # don't step on central controllers TODO: separate central and remote CIQ ingestion
                    csr.ilo_subnet = str(ilo_subnet)
                    csr.ilo_default_gateway = str(ilo_default_gateway)
                    server.server_number = server_number
                    server.ilo_host_address = str(ilo_host_address)
                else:
                    cluster.is_central_controller = 1

                # foreign-key relationships
                cluster.sap_clli = sap_clli
                if assign_parent is True and cluster.parent_cluster is None:
                    cluster.parent_cluster = parent_cluster
                cluster.location = location
                cluster.vlan = vlan
                cluster.csr = csr
                cluster.namespace = namespace
                server.cluster = cluster
                # upsert
                vlan.save()
                namespace.save()
                csr.save()
                sap_clli.save()
                location.save()
                cluster.save()
                server.save()