diff options
Diffstat (limited to 'src/caas/services/helpers.py')
| -rw-r--r-- | src/caas/services/helpers.py | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/caas/services/helpers.py b/src/caas/services/helpers.py new file mode 100644 index 0000000..9145d1f --- /dev/null +++ b/src/caas/services/helpers.py @@ -0,0 +1,136 @@ +import ipaddress +import jinja2 +import os +import subprocess + + +class Shell(): + @staticmethod + def run_shell_command(cmd): + p = subprocess.Popen([cmd], + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env={}) + out, err = p.communicate() + if p.returncode != 0: + raise Exception("Error running shell command:\n%s\n%s" % (out, err)) + return out, err + + +class Jinja(): + @staticmethod + def render(template_name, **kwargs): + cwd = os.path.dirname(os.path.abspath(__file__)) + loader = jinja2.FileSystemLoader([".", "/"]) + extensions = ["jinja2.ext.with_", "jinja2.ext.loopcontrols"] + environment = jinja2.Environment(trim_blocks = True, + lstrip_blocks = True, + extensions = extensions, + loader = loader) + template_names = ["%s/jinja/%s" % (cwd, template_name)] + template = environment.select_template(template_names) + return template.render(kwargs) + + +class RawQuery(): + @staticmethod + def dict_fetchall(cursor): + rows = cursor.fetchall() + if len(rows) == 0: + return None + else: + columns = [col[0] for col in cursor.description] + return [dict(zip(columns, row)) for row in rows] + + @staticmethod + def query_single_value(cursor, query, column_name): + cursor.execute(query) + rows = RawQuery.dict_fetchall(cursor) + if rows == {}: + return None + else: + return rows[0][column_name] + + +class Address(): + @staticmethod + def coalesce(ip, default): + if ip is None: + return default + else: + return ip + + @staticmethod + def get_quads(addr): + return list(filter(lambda x: x, str(addr).split("/")[0].split(":"))) + + @staticmethod + def address_add(ip, index): + return ipaddress.IPv6Address(ip) + index + + """ + Assumes a 5-quad 'subnet' as import input. Adds the 6th quad which is always 40a. + """ + @staticmethod + def add_40a(subnet): + return Address.address_add(subnet, 0x040a00000000) + + @staticmethod + def next_address(ip, subnet, block_begin_hex): + beginning_address = Address.coalesce(ip, Address.address_add(subnet, block_begin_hex)) + if ip is None: + return beginning_address + else: + return Address.address_add(beginning_address, 0x1) + + @staticmethod + def add_cidr(subnet, cidr = 64): + subnet_quads = Address.get_quads(subnet) + return "%s::/%s" % (":".join(subnet_quads), cidr) + + @staticmethod + def remove_cidr(subnet): + return ipaddress.IPv6Address(str(subnet).split("/")[0]) + + @staticmethod + def gateway_to_subnet(gateway, numquads = 5): + # The subnet is always the first 5 quads of the gateway. + # TODO: make sure this holds true in MTCE and labs as well as production. + quads = Address.get_quads(gateway) + return ipaddress.IPv6Address("%s::" % ":".join(quads[:numquads])) + + @staticmethod + def gateway_to_subnet_new(gateway): + quads = Address.get_quads(gateway) + return ipaddress.IPv6Address("%s:40a::" % ":".join(quads[:5])) + + @staticmethod + def subnet_to_4_quads(subnet): + quads = Address.get_quads(gateway) + return ipaddress.IPv6Address("%s::" % ":".join(quads[:4])) + + @staticmethod + def strip_brackets(ip): + return ip.replace("[", "").replace("]", "") + + +class Hostname(): + @staticmethod + def make_oam_hostname(ilo_hostname): + return ilo_hostname.replace("-pe0", "-pe2") + + """ + Note: this method does not deal with the index at the end of the + hostname. Doing so would require database access. This is the + responsibility of the service classes. See dnsservice.py + """ + @staticmethod + def make_vip_hostname(ilo_hostname, cluster_name): + index = int(cluster_name[-3:]) + return "%s-%s" % (ilo_hostname.replace("-pe0", "-pe1")[:-4], f"{index + 0:03}") + + @staticmethod + def increment_hostname(hostname): + index = int(hostname[-3:]) + return "%s-%s" % (hostname[:-4], f"{index + 1:03}") |
