#!/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()