class DomainsAutomator: def __init__(self, args): self.utils = Utils(args) self.hostname = args[0] self.utils.printGreen('Initializing Domains Automator') def create_workload_domain(self, payload): # validations validations_url = 'https://' + self.hostname + '/v1/domains/validations/creations' print('Validating the input....') response = self.utils.post_request(payload, validations_url) if (response['resultStatus'] != 'SUCCEEDED'): print('Validation Failed.') exit(1) # Domain Creation domain_creation_url = self.hostname + '/v1/domains' response = self.utils.post_request(payload, domain_creation_url) print('Creating Domain...') task_url = 'https://' + self.hostname + '/v1/tasks/' + response['id'] print("Domain creation task completed with status: " + self.utils.poll_on_id(task_url, True)) def update_workload_domain(self, payload, domain_id): # validations validations_url = 'https://' + self.hostname + '/v1/domains/' + domain_id + '/validations ' self.utils.printGreen('Validating the input....') response = self.utils.post_request(payload, validations_url) self.utils.printGreen( 'Validation started for import cluster operation. The validation id is: ' + response['id']) validate_poll_url = 'https://' + self.hostname + '/v1/domains/validations/' + response[ 'id'] self.utils.printGreen('Polling on validation api ' + validate_poll_url) time.sleep(10) validation_status = self.utils.poll_on_id(validate_poll_url, False) self.utils.printGreen('Validate domain ended with status: ' + validation_status) if validation_status != 'SUCCEEDED': self.utils.printRed('Validation Failed.') self.utils.print_validation_errors(validate_poll_url) exit(1) # Domain Update input("\033[1m Enter to import cluster..\033[0m") domain_creation_url = 'https://' + self.hostname + '/v1/domains/' + domain_id response = self.utils.patch_request(payload, domain_creation_url) self.utils.printGreen( 'Importing cluster, monitor the status of the task(task-id:' + response['id'] + ') from sddc-manager ui') # task_url = 'https://' + self.hostname + '/v1/tasks/' + response['id'] # print ("Domain creation task completed with status: " + self.utils.poll_on_id(task_url, True)) def get_domains(self): # get domains domains_url = 'https://' + self.hostname + '/v1/domains' self.utils.printGreen('Getting the domains..') response = self.utils.get_request(domains_url) return response
class GetClusters: def __init__(self): print('Get Clusters') self.utils = Utils(sys.argv) self.hostname = sys.argv[1] def get_clusters(self): get_clusters_url = 'https://'+self.hostname+'/v1/clusters/' pprint.pprint(self.utils.get_request(get_clusters_url))
class GetNetworkPools: def __init__(self): print('Get Network Pools') self.utils = Utils(sys.argv) self.hostname = sys.argv[1] def get_network_pools(self): get_network_pools_url = 'https://' + self.hostname + '/v1/network-pools' response = self.utils.get_request(get_network_pools_url) pprint.pprint(response)
class GetNetworkofNetworkPools: def __init__(self): print('Get Network of Network Pools') self.utils = Utils(sys.argv) self.hostname = sys.argv[1] self.network_pool_id = sys.argv[4] self.network_id = sys.argv[5] def get_network_of_network_pool(self): get_network_of_pool_url = 'https://' + self.hostname + '/v1/network-pools/' + self.network_pool_id + '/networks/' + self.network_id pprint.pprint(self.utils.get_request(get_network_of_pool_url))
class GetHosts: def __init__(self): print('Get Hosts') self.utils = Utils(sys.argv) self.hostname = sys.argv[1] def get_hosts(self): get_hosts_url = 'https://'+self.hostname+'/v1/hosts/' response = self.utils.get_request(get_hosts_url) pprint.pprint(response)
class LicenseAutomator: def __init__(self, args): self.utils = Utils(args) self.description = "Select license" self.hostname = args[0] def main_func(self): lcs = self.__get_licenses() selected = {} three_line_separator = ['', '', ''] for k in lcs.keys(): lcsls = lcs[k] self.utils.printCyan("Please choose a {} license:".format(k)) ct = 0 lcsmap = {} for onelcs in lcsls: ct += 1 self.utils.printBold("{}) {}".format( ct, self.__output_license_info(onelcs))) lcsmap[str(ct)] = onelcs selected[k] = lcsmap[self.__valid_option( input("\033[1m Enter your choice(number): \033[0m"), lcsmap.keys())]["key"] print(*three_line_separator, sep='\n') return {"licenseKeys": selected} def __output_license_info(self, licenseobj): return "{} ({})".format(licenseobj["key"], licenseobj["validity"]) def __get_licenses(self): self.utils.printGreen("Getting license information...") url = 'https://' + self.hostname + '/v1/license-keys?productType=VSAN,NSXT' response = self.utils.get_request(url) vsankeys = [{ "key": ele["key"], "validity": ele["licenseKeyValidity"]["licenseKeyStatus"] } for ele in response["elements"] if ele["productType"] == "VSAN"] nsxtkeys = [{ "key": ele["key"], "validity": ele["licenseKeyValidity"]["licenseKeyStatus"] } for ele in response["elements"] if ele["productType"] == "NSXT"] return {"VSAN": vsankeys, "NSX-T": nsxtkeys} def __valid_option(self, inputstr, choices): choice = str(inputstr).strip().lower() if choice in choices: return choice self.utils.printYellow("**Use first choice by default") return list(choices)[0]
class NSXTAutomator: def __init__(self, args): self.utils = Utils(args) self.description = "NSX-T instance deployment" self.hostname = args[0] #If current handling domain is management domain, is_primary must be False def main_func(self, selected_domain_id, is_primary=True): three_line_separator = ['', '', ''] nsxt_instances = self.__get_nsxt_instances(selected_domain_id, is_primary) if is_primary: if len(nsxt_instances) > 0: self.utils.printCyan("Please choose NSX-T instance option:") self.utils.printBold("1) Create new NSX-T instance (default)") self.utils.printBold("2) Use existing NSX-T instance") theoption = self.utils.valid_input( "\033[1m Enter your choice(number): \033[0m", "1", self.__valid_option, ["1", "2"]) else: self.utils.printYellow( "** No shared NSX-T instance was found, you need to create a new one" ) theoption = "1" else: if len(nsxt_instances) == 0: #In a common situation, this is not possible self.utils.printRed( "No shared NSX-T instance discovered in current domain") input("Enter to exit ...") sys.exit(1) else: theoption = "2" print(*three_line_separator, sep='\n') if theoption == "1": return self.option1_new_nsxt_instance() return self.option2_existing_nsxt(nsxt_instances) """ In case of secondary cluster, the NSX-T cluster has to be the same as that of the primary cluster. We don’t need to provide an option to create a new NSX-T cluster or list the NSX-T clusters that are not mapped to the primary cluster. We can identify the NSX-T cluster based on the domain ID (as provided below). In case of primary cluster, the NSX-T cluster could be a new cluster or an existing one. List only the NSX-T clusters that have the property isShareable as TRUE. The management NSX-T cluster is dedicated to management domain and will have the isShareable property set to FALSE. """ def __get_nsxt_instances(self, selected_domain_id, is_primary=True): self.utils.printGreen("Getting shared NSX-T cluster information...") url = 'https://' + self.hostname + '/v1/nsxt-clusters' response = self.utils.get_request(url) nsxinstances = [] for oneins in response["elements"]: if is_primary and oneins["isShareable"]: nsxinstances.append(oneins) elif not is_primary: domainids = [ onedomain["id"] for onedomain in oneins["domains"] ] if selected_domain_id in domainids: nsxinstances.append(oneins) return nsxinstances def option2_existing_nsxt(self, nsxt_instances): three_line_separator = ['', '', ''] geneve_vlan = self.utils.valid_input( "\033[1m Enter Geneve vLAN ID (0-4096): \033[0m ", None, self.__valid_vlan) print(*three_line_separator, sep='\n') self.utils.printCyan("Please select one NSX-T instance") ct = 0 nsxt_map = {} for nsxt_inst in nsxt_instances: idx = str(ct + 1) ct += 1 nsxt_map[idx] = nsxt_inst self.utils.printBold("{0}) NSX-T vip: {1}".format( idx, nsxt_inst["vipFqdn"])) choiceidx = self.utils.valid_input( "\033[1m Enter your choice(number): \033[0m", None, self.__valid_option, nsxt_map.keys()) selected_ins = nsxt_map[choiceidx] print(*three_line_separator, sep='\n') nsxTSpec = { "nsxManagerSpecs": [], "vip": selected_ins["vip"], "vipFqdn": selected_ins["vipFqdn"] } for nsxnode in selected_ins["nodes"]: nsxTSpec["nsxManagerSpecs"].append({ "name": nsxnode["name"], "networkDetailsSpec": { "dnsName": nsxnode["fqdn"], "ipAddress": nsxnode["ipAddress"] } }) return {"nsxTSpec": nsxTSpec, "geneve_vlan": geneve_vlan} def option1_new_nsxt_instance(self): three_line_separator = ['', '', ''] geneve_vlan = self.utils.valid_input( "\033[1m Enter Geneve vLAN ID (0-4096): \033[0m", None, self.__valid_vlan) admin_password = self.__handle_password_input() print(*three_line_separator, sep='\n') self.utils.printCyan("Please Enter NSX-T VIP details") nsxt_vip_fqdn = self.utils.valid_input( "\033[1m FQDN (IP address will be fetched from DNS): \033[0m", None, self.__valid_fqdn) nsxt_gateway = self.utils.valid_input( "\033[1m Gateway IP address: \033[0m", None, self.__valid_ip) nsxt_netmask = self.utils.valid_input( "\033[1m Subnet mask (255.255.255.0): \033[0m", "255.255.255.0", self.__valid_ip) print(*three_line_separator, sep='\n') nsxt_1_fqdn = self.utils.valid_input( "\033[1m Enter FQDN for 1st NSX-T Manager: \033[0m", None, self.__valid_fqdn) print(*three_line_separator, sep='\n') nsxt_2_fqdn = self.utils.valid_input( "\033[1m Enter FQDN for 2nd NSX-T Manager: \033[0m", None, self.__valid_fqdn) print(*three_line_separator, sep='\n') nsxt_3_fqdn = self.utils.valid_input( "\033[1m Enter FQDN for 3rd NSX-T Manager: \033[0m", None, self.__valid_fqdn) print(*three_line_separator, sep='\n') nsxTSpec = { "nsxManagerSpecs": [ self.__to_nsx_manager_obj(nsxt_1_fqdn, nsxt_gateway, nsxt_netmask), self.__to_nsx_manager_obj(nsxt_2_fqdn, nsxt_gateway, nsxt_netmask), self.__to_nsx_manager_obj(nsxt_3_fqdn, nsxt_gateway, nsxt_netmask) ], "vip": self.__nslookup_ip_from_dns(nsxt_vip_fqdn), "vipFqdn": nsxt_vip_fqdn, "nsxManagerAdminPassword": admin_password } return {"nsxTSpec": nsxTSpec, "geneve_vlan": geneve_vlan} def __to_nsx_manager_obj(self, fqdn, gateway, netmask): ip = self.__nslookup_ip_from_dns(fqdn) return { "name": fqdn.split('.')[0], "networkDetailsSpec": { "ipAddress": ip, "dnsName": fqdn, "gateway": gateway, "subnetMask": netmask } } def __valid_option(self, inputstr, choices): choice = str(inputstr).strip().lower() if choice in choices: return choice self.utils.printYellow("**Use first choice by default") return list(choices)[0] def __valid_password(self, inputstr): return self.utils.password_check(inputstr) def __valid_vlan(self, inputstr): res = True if not str(inputstr).isdigit(): res = False res = (int(inputstr) >= 0 and int(inputstr) <= 4096) if not res: self.utils.printRed("VLAN must be a number in between 0-4096") return res def __valid_fqdn(self, inputstr): res = True if len(inputstr) <= 3 or len(inputstr) > 255: res = False elif "." not in inputstr: res = False elif inputstr[0] == "." or inputstr[-1] == ".": res = False else: segmatch = re.compile("[0-9 a-z A-Z _ -]") res = all((len(segmatch.sub('', oneseg)) == 0 and len(oneseg) > 0) for oneseg in inputstr.split(".")) if not res: self.utils.printRed("FQDN format is not correct") else: self.utils.printGreen("Resolving IP from DNS...") theip = self.__nslookup_ip_from_dns(inputstr) if theip is not None: self.utils.printGreen("Resolved IP address: {}".format(theip)) else: res = False self.utils.printRed("Hasn't found matched IP from DNS") return res def __valid_ip(self, inputstr): res = re.compile("(\d+\.\d+\.\d+\.\d+)").match( inputstr) is not None and all((int(seg) >= 0 and int(seg) <= 255) for seg in inputstr.split(".")) if not res: self.utils.printRed("IP format is not correct") return res def __nslookup_ip_from_dns(self, fqdn): cmd = "nslookup {}".format(fqdn) sub_popen = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, err = sub_popen.communicate() if sub_popen.returncode > 0: return None thenext = False # byte feature only supported in python 3 for aline in output.decode('utf8').split("\n"): if thenext and str(aline).lower().startswith("address:"): return aline.split(":")[-1].strip() if str(aline).lower().startswith("name:"): tail = aline.split(":")[-1].strip() if tail == fqdn: thenext = True return None def __handle_password_input(self): while (True): thepwd = getpass.getpass("\033[1m Enter Admin password: \033[0m") confirmpwd = getpass.getpass( "\033[1m Confirm Admin password: \033[0m") if thepwd != confirmpwd: self.utils.printRed("Passwords don't match") else: return thepwd
class NSXTAutomator: def __init__(self, args): self.utils = Utils(args) self.description = "NSX-T instance deployment" self.hostname = args[0] # If current handling domain is management domain, is_primary must be False def main_func(self, selected_domain_id, is_primary=True): three_line_separator = ['', '', ''] nsxt_instances = self.__get_nsxt_instances(selected_domain_id, is_primary) if is_primary: if len(nsxt_instances) > 0: self.utils.printCyan("Please choose NSX-T instance option:") self.utils.printBold("1) Create new NSX-T instance (default)") self.utils.printBold("2) Use existing NSX-T instance") theoption = self.utils.valid_input( "\033[1m Enter your choice(number): \033[0m", "1", self.__valid_option, ["1", "2"]) else: self.utils.printYellow( "** No shared NSX-T instance was found, you need to create a new one" ) theoption = "1" else: if len(nsxt_instances) == 0: # In a common situation, this is not possible self.utils.printRed( "No shared NSX-T instance discovered in current domain") input("Enter to exit ...") sys.exit(1) else: theoption = "2" print(*three_line_separator, sep='\n') if theoption == "1": return self.option1_new_nsxt_instance() return self.option2_existing_nsxt(nsxt_instances) """ In case of secondary cluster, the NSX-T cluster has to be the same as that of the primary cluster. We don’t need to provide an option to create a new NSX-T cluster or list the NSX-T clusters that are not mapped to the primary cluster. We can identify the NSX-T cluster based on the domain ID (as provided below). In case of primary cluster, the NSX-T cluster could be a new cluster or an existing one. List only the NSX-T clusters that have the property isShareable as TRUE. The management NSX-T cluster is dedicated to management domain and will have the isShareable property set to FALSE. """ def __get_nsxt_instances(self, selected_domain_id, is_primary=True): self.utils.printGreen("Getting shared NSX-T cluster information...") url = 'https://' + self.hostname + '/v1/nsxt-clusters' response = self.utils.get_request(url) nsxinstances = [] for oneins in response["elements"]: if is_primary and oneins["isShareable"]: nsxinstances.append(oneins) elif not is_primary: domainids = [ onedomain["id"] for onedomain in oneins["domains"] ] if selected_domain_id in domainids: nsxinstances.append(oneins) return nsxinstances def __get_static_ip_pool(self, nsxt_cluster_id): self.utils.printGreen("Getting Static IP Pool information...") url = 'https://' + self.hostname + '/v1/nsxt-clusters/' + nsxt_cluster_id + '/ip-address-pools' response = self.utils.get_request(url) ip_address_pools = [] for element in response['elements']: ip_address_pools.append(element) return ip_address_pools def __generate_ip_address_pool_ranges(self, inputstr): ip_ranges = [x.strip() for x in inputstr.split(',')] res = [] for ip_range in ip_ranges: ips = ip_range.split('-') res.append({"start": ips[0], "end": ips[1]}) return res def check_overlap_subnets(self, cidrs, input_cidr): if cidrs: for c in cidrs: if ipaddress.IPv4Network(input_cidr).overlaps( ipaddress.IPv4Network(c)): self.utils.printRed( 'Overlapping subnet {} with {}. Please enter valid subnet details...' .format(input_cidr, c)) return True return False def input_subnet(self, subnets, cidrs, count): three_line_separator = ['', '', ''] print(*three_line_separator, sep='\n') self.utils.printCyan("Subnet #{}".format(count)) cidr = self.utils.valid_input("\033[1m Enter CIDR: \033[0m", None, self.__valid_cidr) self.utils.printYellow( "** Multiple IP Ranges are supported by comma separated") ip_ranges = self.utils.valid_input("\033[1m Enter IP Range: \033[0m", None, self.__valid_ip_ranges) gateway_ip = self.utils.valid_input( "\033[1m Enter Gateway IP: \033[0m", None, self.__valid_ip) if self.check_overlap_subnets(cidrs, cidr): self.input_subnet(subnets, cidrs, count) else: cidrs.append(cidr) subnet = { "ipAddressPoolRanges": self.__generate_ip_address_pool_ranges(ip_ranges), "cidr": cidr, "gateway": gateway_ip } subnets.append(subnet) print(*three_line_separator, sep='\n') select_option = input( "\033[1m Do you want to add another subnet ? (Enter 'yes' or 'no'): \033[0m" ) if select_option.lower() == 'yes': self.input_subnet(subnets, cidrs, count + 1) return subnets def create_static_ip_pool(self): self.utils.printCyan("Create New Static IP Pool") pool_name = input("\033[1m Enter Pool Name: \033[0m") description = input("\033[1m Enter Description(Optional): \033[0m") ip_address_pool_spec = { "name": pool_name, "subnets": self.input_subnet([], [], count=1) } if description: ip_address_pool_spec.update({"description": description}) return ip_address_pool_spec def __prepare_ip_address_pool(self, ip_address_pool): ip_address_pool_spec = {"name": ip_address_pool['name']} return ip_address_pool_spec def option2_existing_nsxt(self, nsxt_instances): three_line_separator = ['', '', ''] geneve_vlan = self.utils.valid_input( "\033[1m Enter Geneve vLAN ID (0-4096): \033[0m ", None, self.__valid_vlan) print(*three_line_separator, sep='\n') self.utils.printCyan("Please select one NSX-T instance") ct = 0 nsxt_map = {} for nsxt_inst in nsxt_instances: idx = str(ct + 1) ct += 1 nsxt_map[idx] = nsxt_inst self.utils.printBold("{0}) NSX-T vip: {1}".format( idx, nsxt_inst["vipFqdn"])) choiceidx = self.utils.valid_input( "\033[1m Enter your choice(number): \033[0m", None, self.__valid_option, nsxt_map.keys()) selected_ins = nsxt_map[choiceidx] print(*three_line_separator, sep='\n') self.utils.printCyan("Please choose IP Allocation for TEP IPs option:") self.utils.printBold("1) DHCP (default)") self.utils.printBold("2) Static IP Pool") selected_option = self.utils.valid_input( "\033[1m Enter your choice(number): \033[0m", "1", self.__valid_option, ["1", "2"]) print(*three_line_separator, sep='\n') ip_address_pool_spec = None if selected_option == "2": self.utils.printCyan("Select the option for Static IP Pool:") self.utils.printBold("1) Create New Static IP Pool(default)") self.utils.printBold("2) Re-use an Existing Static Pool") static_ip_pool_option = self.utils.valid_input( "\033[1m Enter your choice(number): \033[0m", "1", self.__valid_option, ["1", "2"]) print(*three_line_separator, sep='\n') if static_ip_pool_option == "1": ip_address_pool_spec = self.create_static_ip_pool() elif static_ip_pool_option == "2": ip_address_pools = self.__get_static_ip_pool( selected_ins["id"]) print(*three_line_separator, sep='\n') if not ip_address_pools: self.utils.printRed( "No existing Static IP Pools are getting discovered..." ) input("\033[1m Enter to exit ...\033[0m") sys.exit(1) self.utils.printCyan("Please select one static ip pool:") self.utils.printBold( "-----Pool Name-------------------Subnets---------------------------Available IPs--" ) self.utils.printBold( "----------------------------------------------------------------------------------" ) count = 0 ip_pool_map = {} for ip_address_pool in ip_address_pools: count += 1 pool_name = '{}) {} : '.format(count, ip_address_pool['name']) self.utils.printBold( '{} Static/Block Subnets {}: {}'.format( pool_name, 30 * ' ', ip_address_pool['availableIpAddresses'])) if ip_address_pool['staticSubnets']: self.utils.printBold('{} Static Subnets '.format( len(pool_name) * ' ')) print( "{}\033[36m -----CIDR-------------IP Ranges-----------" .format(len(pool_name) * ' ')) for static_subnet in ip_address_pool['staticSubnets']: ip_ranges = [] for ip_range in static_subnet[ 'ipAddressPoolRanges']: ip_ranges.append('{}-{}'.format( ip_range['start'], ip_range['end'])) print("\033[36m {} {} : {}".format( len(pool_name) * ' ', static_subnet['cidr'], ip_ranges)) if 'blockSubnets' in ip_address_pool: self.utils.printBold('{} Block Subnets '.format( len(pool_name) * ' ')) print( "{}\033[36m -----CIDR-------------Size----------------" .format(len(pool_name) * ' ')) for block_subnet in ip_address_pool['blockSubnets']: print("\033[36m {} {} : {}".format( len(pool_name) * ' ', block_subnet['cidr'], block_subnet['size'])) ip_pool_map[str(count)] = self.__prepare_ip_address_pool( ip_address_pool) print('\n') choice = self.utils.valid_input( "\033[0;1m Enter your choice(number): \033[0m", None, self.__valid_option, ip_pool_map.keys()) ip_address_pool_spec = ip_pool_map[choice] print(*three_line_separator, sep='\n') nsxTSpec = { "nsxManagerSpecs": [], "vip": selected_ins["vip"], "vipFqdn": selected_ins["vipFqdn"] } for nsxnode in selected_ins["nodes"]: nsxTSpec["nsxManagerSpecs"].append({ "name": nsxnode["name"], "networkDetailsSpec": { "dnsName": nsxnode["fqdn"], "ipAddress": nsxnode["ipAddress"] } }) if ip_address_pool_spec is not None: nsxTSpec.update({"ipAddressPoolSpec": ip_address_pool_spec}) return {"nsxTSpec": nsxTSpec, "geneve_vlan": geneve_vlan} def option1_new_nsxt_instance(self): three_line_separator = ['', '', ''] geneve_vlan = self.utils.valid_input( "\033[1m Enter Geneve vLAN ID (0-4096): \033[0m", None, self.__valid_vlan) admin_password = self.__handle_password_input() print(*three_line_separator, sep='\n') self.utils.printCyan("Please Enter NSX-T VIP details") nsxt_vip_fqdn = self.utils.valid_input( "\033[1m FQDN (IP address will be fetched from DNS): \033[0m", None, self.__valid_fqdn) nsxt_gateway = self.utils.valid_input( "\033[1m Gateway IP address: \033[0m", None, self.__valid_ip) nsxt_netmask = self.utils.valid_input( "\033[1m Subnet mask (255.255.255.0): \033[0m", "255.255.255.0", self.__valid_ip) print(*three_line_separator, sep='\n') nsxt_1_fqdn = self.utils.valid_input( "\033[1m Enter FQDN for 1st NSX-T Manager: \033[0m", None, self.__valid_fqdn) print(*three_line_separator, sep='\n') nsxt_2_fqdn = self.utils.valid_input( "\033[1m Enter FQDN for 2nd NSX-T Manager: \033[0m", None, self.__valid_fqdn) print(*three_line_separator, sep='\n') nsxt_3_fqdn = self.utils.valid_input( "\033[1m Enter FQDN for 3rd NSX-T Manager: \033[0m", None, self.__valid_fqdn) print(*three_line_separator, sep='\n') self.utils.printCyan("Please choose IP Allocation for TEP IPs option:") self.utils.printBold("1) DHCP (default)") self.utils.printBold("2) Static IP Pool") selected_option = self.utils.valid_input( "\033[1m Enter your choice(number): \033[0m", "1", self.__valid_option, ["1", "2"]) ip_address_pool_spec = None if selected_option == "2": print(*three_line_separator, sep='\n') ip_address_pool_spec = self.create_static_ip_pool() print(*three_line_separator, sep='\n') nsxTSpec = { "nsxManagerSpecs": [ self.__to_nsx_manager_obj(nsxt_1_fqdn, nsxt_gateway, nsxt_netmask), self.__to_nsx_manager_obj(nsxt_2_fqdn, nsxt_gateway, nsxt_netmask), self.__to_nsx_manager_obj(nsxt_3_fqdn, nsxt_gateway, nsxt_netmask) ], "vip": self.__nslookup_ip_from_dns(nsxt_vip_fqdn), "vipFqdn": nsxt_vip_fqdn, "nsxManagerAdminPassword": admin_password } if ip_address_pool_spec is not None: nsxTSpec.update({"ipAddressPoolSpec": ip_address_pool_spec}) return {"nsxTSpec": nsxTSpec, "geneve_vlan": geneve_vlan} def __to_nsx_manager_obj(self, fqdn, gateway, netmask): ip = self.__nslookup_ip_from_dns(fqdn) return { "name": fqdn.split('.')[0], "networkDetailsSpec": { "ipAddress": ip, "dnsName": fqdn, "gateway": gateway, "subnetMask": netmask } } def __valid_option(self, inputstr, choices): choice = str(inputstr).strip().lower() if choice in choices: return choice self.utils.printYellow("**Use first choice by default") return list(choices)[0] def __valid_password(self, inputstr): return self.utils.password_check(inputstr) def __valid_vlan(self, inputstr): res = True if not str(inputstr).isdigit(): res = False res = (int(inputstr) >= 0 and int(inputstr) <= 4096) if not res: self.utils.printRed("VLAN must be a number in between 0-4096") return res def __valid_fqdn(self, inputstr): res = True if len(inputstr) <= 3 or len(inputstr) > 255: res = False elif "." not in inputstr: res = False elif inputstr[0] == "." or inputstr[-1] == ".": res = False else: segmatch = re.compile("[0-9 a-z A-Z _ -]") res = all((len(segmatch.sub('', oneseg)) == 0 and len(oneseg) > 0) for oneseg in inputstr.split(".")) if not res: self.utils.printRed("FQDN format is not correct") else: self.utils.printGreen("Resolving IP from DNS...") theip = self.__nslookup_ip_from_dns(inputstr) if theip is not None: self.utils.printGreen("Resolved IP address: {}".format(theip)) else: res = False self.utils.printRed("Hasn't found matched IP from DNS") return res def __valid_ip(self, inputstr): res = re.compile("(\d+\.\d+\.\d+\.\d+)$").match( inputstr) is not None and all((int(seg) >= 0 and int(seg) <= 255) for seg in inputstr.split(".")) if not res: self.utils.printRed("IP format is not correct") return res def __valid_cidr(self, inputstr): pattern = r'(\d+\.\d+\.\d+\.\d+)\/([0-9]|[1-2][0-9]|3[0-2])$' res = re.match(pattern, inputstr) is not None and all( (0 <= int(seg) <= 255) for seg in re.search(pattern, inputstr).group(1).split(".")) if not res: self.utils.printRed("CIDR format is not correct") return res # IP Ranges will be in form of eg.10.0.0.1-10.0.0.10, 10.0.0.20-10.0.0.30 def __valid_ip_ranges(self, inputstr): ip_ranges: List[Any] = [x.strip() for x in inputstr.split(',')] for ip_range in ip_ranges: try: start_ip, end_ip = ip_range.split('-') except ValueError: self.utils.printRed("IP Range format is not correct") return None res = self.__valid_ip(start_ip) and self.__valid_ip(end_ip) if not res: return res return True def __nslookup_ip_from_dns(self, fqdn): cmd = "nslookup {}".format(fqdn) sub_popen = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, err = sub_popen.communicate() if sub_popen.returncode > 0: return None thenext = False # byte feature only supported in python 3 for aline in output.decode('utf8').split("\n"): if thenext and str(aline).lower().startswith("address:"): return aline.split(":")[-1].strip() if str(aline).lower().startswith("name:"): tail = aline.split(":")[-1].strip() if tail == fqdn: thenext = True return None def __handle_password_input(self): while (True): thepwd = getpass.getpass("\033[1m Enter Admin password: \033[0m") confirmpwd = getpass.getpass( "\033[1m Confirm Admin password: \033[0m") if thepwd != confirmpwd: self.utils.printRed("Passwords don't match") else: return thepwd