def build_virtual_service(self, service, response=None): """Create a VirtualService instance with populated with API parameters This does not include potentially attached real servers :param service: OrderedDict populated with virtual service data :param response: Optional response of a listvs call. This acts as a cache, if you want to create a lot of VirtualService objects in a row, such as with looping, you can call listvs and pass the response in each time and this will nullify the extra listvs calls. :return: VirtualService object with populated attributes """ is_sub_vs = True if int(service.get('MasterVSID', 0)) != 0 else False if is_sub_vs: # `response` needs to be a dict in here # Add lb properties to the sub vs if response is None: response = self._get("/showvs", {"vs": service.get('MasterVSID')}) parent_vs_data = get_data(response) else: parent_vs_data = response subvs_lb_props = get_sub_vs_list_from_data(parent_vs_data)[1] virt_serv = VirtualService(self.access_info, service.get('Index'), is_sub_vs=True) virt_serv.subvs_data = subvs_lb_props[service.get('Index')] virt_serv.subvs_data['parentvs'] = service.get('MasterVSID') else: # `response` needs to be a raw xml output here # Add any sub VSs to the top level VS if response is None: response = self._get("/listvs") data = get_data(response) virt_serv = VirtualService(self.access_info, service.get('VSAddress'), service.get('VSPort'), service.get('Protocol'), is_sub_vs=False) virt_serv.subvs_entries = [] services = get_dict_entry_as_list("VS", data) this_vs_index = service.get('Index') for vs in services: # add subvs to parent vs if vs['MasterVSID'] == this_vs_index: subvs = VirtualService(self.access_info, vs['Index'], is_sub_vs=True) subvs.populate_default_attributes(vs) subvs_api_entries = service.get("SubVS", []) subvs_api_entries = cast_to_list(subvs_api_entries) for subvs_api in subvs_api_entries: # add the "Rs" part of the subvs to the subvs instance if subvs_api["VSIndex"] == subvs.index: subvs.subvs_data = subvs_api # Have to add a parentvs hook to make life easy subvs.subvs_data['parentvs'] = this_vs_index virt_serv.subvs_entries.append(subvs) virt_serv.populate_default_attributes(service) return virt_serv
def get_all_objects(self): # x variables are the object while x_data is the OrderedDict virtual_services = [] response = self._get("/listvs") data = get_data(response) virtual_services_data = data.get('VS', []) virtual_services_data = cast_to_list(virtual_services_data) # create vs and rs objects at this point # loop through all vss and attach matching real server objects for service_data in virtual_services_data: master_vs_id = int(service_data.get('MasterVSID', 0)) if master_vs_id != 0: for vs in virtual_services_data: if int(vs.get("Index", 0)) == master_vs_id: virt_serv = self.build_virtual_service(service_data, vs) else: virt_serv = self.build_virtual_service(service_data, response) real_servers = cast_to_list(service_data.get("Rs", [])) for server_data in real_servers: rs = virt_serv.build_real_server(server_data) virt_serv.real_servers.append(rs) virtual_services.append(virt_serv) # replace subvs's with vs's that have RSs in them. for vs in virtual_services: for subvs in vs.subvs_entries: for top_level_vs in virtual_services: if subvs.index == top_level_vs.index: subvs.real_servers = top_level_vs.real_servers return virtual_services
def get_all_parameters(self): """ Return all parameters as a dict with lowercase keys :return: A dict of all the parameters, with the keys in lowercase """ response = self._get("/getall") data = get_data(response) return dict((k.lower(), v) for k, v in data.items())
def get_acl_settings(self): response = self._get("/geoacl/getsettings") if is_successful(response): data = get_data(response) data = data['GeoAcl'] else: raise KempTechApiException(get_error_msg(response)) acl_settings = {} for k, v in data.items(): if v == "yes": v = True elif v == "no": v = False elif v == "Never": v = None else: try: v = int(v) # pylint: disable=redefined-variable-type except ValueError: pass acl_settings[k.lower()] = v return acl_settings
def test_list_object(): lm = LoadMaster("1.1.1.1", "bal", "2fourall") vs = lm.create_virtual_service("1.1.1.2") response = "<Response stat=\"200\" code=\"ok\"> <Success> <Data> <VS> <Status>Down</Status> <Index>1</Index> <VSAddress>10.154.75.123</VSAddress> <VSPort>80</VSPort> <Enable>Y</Enable> <SSLReverse>N</SSLReverse> <SSLReencrypt>N</SSLReencrypt> <Intercept>N</Intercept> <InterceptOpts> <Opt>opnormal</Opt> <Opt>auditrelevant</Opt> <Opt>reqdatadisable</Opt> <Opt>resdatadisable</Opt> </InterceptOpts> <AlertThreshold>0</AlertThreshold> <Transactionlimit>0</Transactionlimit> <Transparent>Y</Transparent> <SubnetOriginating>N</SubnetOriginating> <ServerInit>0</ServerInit> <StartTLSMode>0</StartTLSMode> <Idletime>0</Idletime> <Cache>N</Cache> <Compress>N</Compress> <Verify>0</Verify> <UseforSnat>N</UseforSnat> <ForceL7>Y</ForceL7> <MultiConnect>N</MultiConnect> <ClientCert>0</ClientCert> <ErrorCode>0</ErrorCode> <CheckUse1.1>N</CheckUse1.1> <MatchLen>0</MatchLen> <CheckUseGet>0</CheckUseGet> <SSLRewrite>0</SSLRewrite> <VStype>http</VStype> <FollowVSID>0</FollowVSID> <Protocol>tcp</Protocol> <Schedule>rr</Schedule> <CheckType>http</CheckType> <PersistTimeout>0</PersistTimeout> <CheckPort>0</CheckPort> <NRules>0</NRules> <NRequestRules>0</NRequestRules> <NResponseRules>0</NResponseRules> <NPreProcessRules>0</NPreProcessRules> <EspEnabled>N</EspEnabled> <InputAuthMode>0</InputAuthMode> <OutputAuthMode>0</OutputAuthMode> <MasterVS>0</MasterVS> <MasterVSID>0</MasterVSID> <AddVia>0</AddVia> <QoS>0</QoS> <TlsType>0</TlsType> <NeedHostName>N</NeedHostName> <OCSPVerify>N</OCSPVerify> <EnhancedHealthChecks>N</EnhancedHealthChecks> <RsMinimum>0</RsMinimum> <NumberOfRSs>0</NumberOfRSs> </VS> <VS> <Status>Down</Status> <Index>2</Index> <VSAddress>10.154.190.229</VSAddress> <VSPort>80</VSPort> <Enable>Y</Enable> <SSLReverse>N</SSLReverse> <SSLReencrypt>N</SSLReencrypt> <Intercept>N</Intercept> <InterceptOpts> <Opt>opnormal</Opt> <Opt>auditrelevant</Opt> <Opt>reqdatadisable</Opt> <Opt>resdatadisable</Opt> </InterceptOpts> <AlertThreshold>0</AlertThreshold> <Transactionlimit>0</Transactionlimit> <Transparent>Y</Transparent> <SubnetOriginating>N</SubnetOriginating> <ServerInit>0</ServerInit> <StartTLSMode>0</StartTLSMode> <Idletime>0</Idletime> <Cache>N</Cache> <Compress>N</Compress> <Verify>0</Verify> <UseforSnat>N</UseforSnat> <ForceL7>Y</ForceL7> <MultiConnect>N</MultiConnect> <ClientCert>0</ClientCert> <ErrorCode>0</ErrorCode> <CheckUse1.1>N</CheckUse1.1> <MatchLen>0</MatchLen> <CheckUseGet>0</CheckUseGet> <SSLRewrite>0</SSLRewrite> <VStype>http</VStype> <FollowVSID>0</FollowVSID> <Protocol>tcp</Protocol> <Schedule>rr</Schedule> <CheckType>http</CheckType> <PersistTimeout>0</PersistTimeout> <CheckPort>0</CheckPort> <NRules>0</NRules> <NRequestRules>0</NRequestRules> <NResponseRules>0</NResponseRules> <NPreProcessRules>0</NPreProcessRules> <EspEnabled>N</EspEnabled> <InputAuthMode>0</InputAuthMode> <OutputAuthMode>0</OutputAuthMode> <MasterVS>0</MasterVS> <MasterVSID>0</MasterVSID> <AddVia>0</AddVia> <QoS>0</QoS> <TlsType>0</TlsType> <NeedHostName>N</NeedHostName> <OCSPVerify>N</OCSPVerify> <EnhancedHealthChecks>N</EnhancedHealthChecks> <RsMinimum>0</RsMinimum> <NumberOfRSs>0</NumberOfRSs> </VS> </Data> </Success> </Response>" data = get_data(response) vss = list_object(VirtualService, vs.access_info, data) assert_equal(2, len(vss))
def get_sso(self, name): service_id = {"name": name} response = self._get("/showdomain", service_id) sso = get_data(response).get("Domain") # again line below will fail with ValidationError if empty response sso_object = self.build_sso(sso) return sso_object
def get_fqdns(self): try: response = self._get("/listfqdns") data = get_data(response) return list_object(Fqdn, self.access_info, data) except KempTechApiException: # If API returns 'No geo data found' return an empty list return []
def get_check_parameters(self): response = self._get("/showhealth") data = get_data(response) formatted = {} for k, v in data.items(): formatted[k.lower()] = int(v) return formatted
def get_range(self, ip): service_id = {"ipaddress": ip} response = self._get("/showip", service_id) data = get_data(response) # again line below will fail with ValidationError if empty response range_data = data.get('cluster', {}) if not isinstance(range_data, dict): raise LoadMasterParameterError( "Unexepected number of ranges returned", range_data) return self.build_range(range_data)
def get_intermediate_certificates(self, type='cert'): response = self._get("/listintermediate") data = get_data(response) certificates = [] certs = data.get('cert', []) if not isinstance(certs, list): certs = [certs] for cert in certs: certificate = self.build_intermediate_certificate(cert) certificates.append(certificate) return certificates
def get_eula(self): api = "/readeula" response = self._get(api) if is_successful(response): data = get_data(response) else: raise KempTechApiException(get_error_msg(response)) self.magic = data['Magic'] return data['Eula']
def get_cluster(self, ip): service_id = {"ip": ip} response = self._get("/showcluster", service_id) data = get_data(response) cluster_data = data.get('cluster') # again line below will fail with ValidationError if empty response if not isinstance(cluster_data, dict): raise LoadMasterParameterError( "Unexepected number of clusters returned", cluster_data) cluster = self.build_cluster(cluster_data) return cluster
def get_rules(self): response = self._get("/showrule") data = get_data(response) rules_list = [] for rule_type, rules in data.items(): rules = cast_to_list(rules) for rule in rules: rule['type'] = rule_type rule_object = build_object(Rule, self.access_info, rule) rules_list.append(rule_object) return rules_list
def get_clusters(self): try: response = self._get("/listclusters") data = get_data(response) clusters = data.get('cluster', []) except KempTechApiException: clusters = [] cluster_list = [] clusters = cast_to_list(clusters) for c in clusters: cluster = self.build_cluster(c) cluster_list.append(cluster) return cluster_list
def get_customlocations(self): try: response = self._get("/listcustomlocation") data = get_data(response) customlocations = data.get('location', []) except KempTechApiException: customlocations = [] customlocation_list = [] customlocations = cast_to_list(customlocations) for c in customlocations: customlocation = self.build_customlocation(c) customlocation_list.append(customlocation) return customlocation_list
def get_ranges(self): try: response = self._get("/listips") data = get_data(response) ranges = data.get('IPAddress', []) except KempTechApiException: ranges = [] range_list = [] ranges = cast_to_list(ranges) for r in ranges: range = self.build_range(r) range_list.append(range) return range_list
def get_fqdn(self, fqdn): service_id = { "fqdn": fqdn } # Append a . to the fqdn if it does not # exist as it is required for FQDN syntax if service_id['fqdn'][-1] != ".": service_id['fqdn'] += "." response = self._get("/showfqdn", service_id) data = get_data(response) fqdn = build_object(Fqdn, self.access_info, data) return fqdn
def get_virtual_service(self, index=None, address=None, port=None, protocol=None): if index is None: validate_ip(address) validate_port(port) validate_protocol(protocol) service_id = {"vs": address, "port": port, "prot": protocol} else: service_id = {"vs": index} response = self._get("/showvs", service_id) service = get_data(response) # again line below will fail with ValidationError if empty response virt_serv = self.build_virtual_service(service) return virt_serv
def get_interfaces(self): interfaces = [] try: response = self._get('/showiface') data = get_data(response) interfaces_data = data.get('Interface', []) interfaces_data = cast_to_list(interfaces_data) for iface_data in interfaces_data: iface = build_object(Interface, self.access_info, iface_data) # Check for duplicate IPs as there is a bug in LoadMaster showiface # that makes unset interfaces inherit the previous interfaces IP. for interface in interfaces: if iface.addr == interface.addr: break else: interfaces.append(iface) return interfaces except KempTechApiException as e: # If showiface does not support listing of all interfaces (possibly due to # older version loadmasters) do it the hard way by doing it one by one getting # the IDs from /access/stats. # This will cause N+1 API calls to occur, N being the number of interfaces. if hasattr(e, "status_code") and e.status_code == 422: try: response = self._get('/stats') data = get_data(response) xml_object = data.get('Network', {}) except KempTechApiException: xml_object = {} for k, v in xml_object.items(): obj = self.get_interface(v['ifaceID']) obj.name = k interfaces.append(obj) return interfaces else: raise
def get_ssos(self): response = self._get("/showdomain") ssos = get_data(response).get("Domain") or [] ssos_list = [] # if there is no Rule key, build_virtual_services will fail with a # ValidationError, which is the best we can do for now # (without changing the upstream code and raising an exception earlier, # possibly retrying) if not isinstance(ssos, list): ssos = [ssos] for sso in ssos: sso_object = self.build_sso(sso) ssos_list.append(sso_object) return ssos_list
def get_virtual_services(self): response = self._get("/listvs") data = get_data(response) virtual_services = [] services = data.get('VS', []) services = cast_to_list(services) for service in services: master_vs_id = int(service.get('MasterVSID', 0)) if master_vs_id != 0: for vs in services: if int(vs.get("Index", 0)) == master_vs_id: virt_serv = self.build_virtual_service(service, vs) else: virt_serv = self.build_virtual_service(service, response) virtual_services.append(virt_serv) return virtual_services
def accept_eula(self, license_type="trial"): api = "/accepteula" parameters = { "type": license_type, "magic": self.magic } response = self._get(api, parameters=parameters) if is_successful(response): data = get_data(response) else: raise KempTechApiException(get_error_msg(response)) self.magic = data['Magic']
def get_customlocation(self, name): service_id = {"name": name} response = self._get("/listcustomlocation", service_id) data = get_data(response) # again line below will fail with ValidationError if empty response customlocations_data = data.get('location', {}) customlocation_data = [x for x in customlocations_data if x['Name'] == name] if not isinstance(customlocation_data, dict): raise LoadMasterParameterError( "Unexepected number of custom locations returned", customlocation_data) customlocation = self.build_range(customlocation_data) return customlocation
def get_rule(self, name): response = self._get("/showrule", {"name": name}) data = get_data(response) rules_list = [] rule_object = None if len(data) > 1: raise KempTechApiException("Too many rules returned") for rule_type, rules in data.items(): rules = cast_to_list(rules) for rule in rules: rule['type'] = rule_type rule_object = build_object(Rule, self.access_info, rule) rules_list.append(rule_object) return rule_object
def get_geo_parameter(self, parameter): """get the value of the given GEO parameter :param parameter: a valid GEO parameter. :type parameter: str. :return: str -- the parameter value """ def _find_key_recursive(d, key): match = [k for k, v in d.items() if k.lower() == key.lower()] if match: return d[match.pop()] for v in d.values(): if isinstance(v, dict): item = _find_key_recursive(v, key) if item is not None: return item response = self._get('/listparams') data = get_data(response) value = _find_key_recursive(data, parameter) return value
def license(self): """Current license on the LoadMaster :return: License information """ response = self._get("/licenseinfo") if is_successful(response): data = get_data(response) license_info = {} # Fix annoying API weirdness for k, v in data.items(): k = k.lower() try: if v[0] == '"': v = v[1:] if v[-1] == '"': v = v[:-1] if v[-1] == "\n": v = v[:-1] except (IndexError, KeyError): # Catch scenarios where there is no data pass if isinstance(v, str): v = v.replace(" ", " ") license_info[k] = v else: raise KempTechApiException(get_error_msg(response)) return license_info
def get_acl(self, type): parameters = { "type": type } response = self._get("/geoacl/listcustom", parameters) if is_successful(response): data = get_data(response) else: raise KempTechApiException(get_error_msg(response)) list_tag = "{}list".format(type).capitalize() acl_list = data[list_tag] if acl_list is None: acl_list = [] elif isinstance(acl_list, dict): acl_list = acl_list.get('addr') if not isinstance(acl_list, list): acl_list = [acl_list] return acl_list
def get_templates(self): response = self._get("/listtemplates") data = get_data(response) return list_object(Template, self.access_info, data)
def get_interface(self, interface): response = self._get("/showiface", {"interface": interface}) xml_object = get_data(response) obj = build_object(Interface, self.access_info, xml_object) return obj
def get_adaptive_parameters(self): response = self._get("/showadaptive") data = get_data(response) return data['Data']