#!/usr/bin/env python3 from __future__ import print_function import pickle import os.path import os from googleapiclient.discovery import build from google_auth_oauthlib.flow import InstalledAppFlow from google.auth.transport.requests import Request import smtplib from email.message import EmailMessage import sys import re import subprocess import CLEUCreds from cleu.config import Config as C FROM = "Joe Clarke " CC = "Kris Sekula , Anthony Jesani " JUMP_HOSTS = ["10.100.252.26", "10.100.252.27", "10.100.252.28", "10.100.252.29"] DC_MAP = {"DC1": "dc1_datastore_1", "DC2": "dc2_datastore_1", "HyperFlex-DC1": "DC1-HX-DS-01", "HyperFlex-DC2": "DC2-HX-DS-01"} DEFAULT_CLUSTER = "FlexPod" HX_DCs = {"HyperFlex-DC1": 1, "HyperFlex-DC2": 1} IP4_SUBNET = "10.100." IP6_PREFIX = "2a05:f8c0:2:" NETWORK_MAP = { "CROSS DC VMs": { "subnet": "{}252.0/24".format(IP4_SUBNET), "gw": "{}252.254".format(IP4_SUBNET), "prefix": "{}64fc::".format(IP6_PREFIX), "gw6": "{}64fc::fe".format(IP6_PREFIX), }, "DC1 ONLY VMs": { "subnet": "{}253.0/24".format(IP4_SUBNET), "gw": "{}253.254".format(IP4_SUBNET), "prefix": "{}64fd::".format(IP6_PREFIX), "gw6": "{}64fd::fe".format(IP6_PREFIX), }, "DC2 ONLY VMs": { "subnet": "{}254.0/24".format(IP4_SUBNET), "gw": "{}254.254".format(IP4_SUBNET), "prefix": "{}64fe::".format(IP6_PREFIX), "gw6": "{}64fe::fe".format(IP6_PREFIX), }, } OSTYPE_LIST = [ (r"(?i)ubuntu", "ubuntu64Guest"), (r"(?i)windows 10", "windows9_64Guest"), (r"(?i)windows 2012", "windows8Server64Guest"), (r"(?i)windows 201(6|9)", "windows9Server64Guest"), (r"(?i)debian 8", "debian8_64Guest"), (r"(?i)debian", "debian9_64Guest"), (r"(?i)centos 7", "centos7_64Guest"), (r"(?i)centos", "centos8_64Guest"), (r"(?i)red hat", "rhel7_64Guest"), (r"(?i)linux", "other3xLinux64Guest"), ] DNS1 = "10.100.253.6" DNS2 = "10.100.254.6" NTP1 = "10.128.0.1" NTP2 = "10.128.0.2" VCENTER = "https://" + C.VCENTER DOMAIN = C.DNS_DOMAIN AD_DOMAIN = C.AD_DOMAIN SMTP_SERVER = C.SMTP_SERVER SYSLOG = SMTP_SERVER ISO_DS = "dc1_datastore_1" ISO_DS_HX1 = "DC1-HX-DS-01" ISO_DS_HX2 = "DC2-HX-DS-01" VPN_SERVER = C.VPN_SERVER VPN_SERVER_IP = C.VPN_SERVER_IP ANSIBLE_PATH = "/home/jclarke/src/git/ciscolive/automation/cleu-ansible-n9k" UPDATE_DNS_PATH = "/home/jclarke" DATACENTER = "CiscoLive" CISCOLIVE_YEAR = C.CISCOLIVE_YEAR PW_RESET_URL = C.PW_RESET_URL SPREADSHEET_ID = "1ExTNQJ7SArHSJKfPOj_x1O2aTj76dHjlG8kCDHW39hw" SHEET_HOSTNAME = 0 SHEET_OS = 1 SHEET_OVA = 2 SHEET_CONTACT = 4 SHEET_CPU = 5 SHEET_RAM = 6 SHEET_DISK = 7 SHEET_NICS = 8 SHEET_DC = 11 SHEET_IP = 12 SHEET_VLAN = 13 def main(): if len(sys.argv) != 2: print("usage: {} ROW_RANGE".format(sys.argv[0])) sys.exit(1) if not os.path.exists("gs_token.pickle"): print("ERROR: Google Sheets token does not exist! Please re-auth the app first.") sys.exit(1) creds = None with open("gs_token.pickle", "rb") as token: creds = pickle.load(token) if "VMWARE_USER" not in os.environ or "VMWARE_PASSWORD" not in os.environ: print("ERROR: VMWARE_USER and VMWARE_PASSWORD environment variables must be set prior to running!") sys.exit(1) gs_service = build("sheets", "v4", credentials=creds) vm_sheet = gs_service.spreadsheets() vm_result = vm_sheet.values().get(spreadsheetId=SPREADSHEET_ID, range=sys.argv[1]).execute() vm_values = vm_result.get("values", []) if not vm_values: print("ERROR: Did not read anything from Google Sheets!") sys.exit(1) (rstart, rend) = sys.argv[1].split(":") i = int(rstart) - 1 users = {} for row in vm_values: i += 1 try: owners = row[SHEET_CONTACT].strip().split(",") name = row[SHEET_HOSTNAME].strip() opsys = row[SHEET_OS].strip() is_ova = row[SHEET_OVA].strip() cpu = int(row[SHEET_CPU].strip()) mem = int(row[SHEET_RAM].strip()) disk = int(row[SHEET_DISK].strip()) dc = row[SHEET_DC].strip() vlan = row[SHEET_VLAN].strip() ip = row[SHEET_IP].strip() except Exception as e: print("WARNING: Failed to process malformed row {}: {}".format(i, e)) continue if name == "" or ip == "" or dc == "": print("WARNING: Ignorning malformed row {}".format(i)) continue for owner in owners: owner = owner.strip() if owner not in users: users[owner] = [] vm = { "name": name.upper(), "os": opsys, "mem": mem, "is_ova": is_ova, "cpu": cpu, "disk": disk, "vlan": vlan, "ip": ip, "dc": dc, } users[owner].append(vm) for user, vms in users.items(): m = re.search(r" {}===".format(vm["name"], vm["ip"])) os.chdir(UPDATE_DNS_PATH) command = ["{}/update_dns.py".format(UPDATE_DNS_PATH), "--ip", vm["ip"], "--host", vm["name"]] p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) output = "" for c in iter(lambda: p.stdout.read(1), b""): output += c.decode("utf-8") p.wait() rc = p.returncode if rc != 0: print("\n\n***ERROR: Failed to add DNS record!\n{}".format(output)) continue print("===DONE===") octets = vm["ip"].split(".") body += '{} : {} (v6: {}{}) (Network: {}, Subnet: {}, GW: {}, v6 Prefix: {}/64, v6 GW: {}) : Deploy to the {} datastore in the "{}" cluster.\r\n\r\nFor this VM upload ISOs to the {} datastore. There is an "ISOs" folder there already.\r\n\r\n'.format( vm["name"], vm["ip"], NETWORK_MAP[vm["vlan"]]["prefix"], format(int(octets[3]), "x"), vm["vlan"], NETWORK_MAP[vm["vlan"]]["subnet"], NETWORK_MAP[vm["vlan"]]["gw"], NETWORK_MAP[vm["vlan"]]["prefix"], NETWORK_MAP[vm["vlan"]]["gw6"], DC_MAP[vm["dc"]], cluster, iso_ds, ) created[vm["name"]] = True body += "Let us know via Webex Teams if you need any other details.\r\n\r\n" body += "Joe, Kris and Anthony\r\n\r\n" subject = "Cisco Live Europe {} Data Centre Access Info".format(CISCOLIVE_YEAR) smtp = smtplib.SMTP(SMTP_SERVER) msg = EmailMessage() msg.set_content(body) msg["Subject"] = subject msg["From"] = FROM msg["To"] = user msg["Cc"] = CC + "," + FROM smtp.send_message(msg) smtp.quit() if __name__ == "__main__": main()