def convert_vs(self, vs_name, f5_vs, vs_state, avi_config, snat_config, user_ignore, tenant_ref, cloud_name, controller_version, merge_object_mapping, sys_dict, f5_config, vrf=None): """ :param vs_name: name of virtual service. :param f5_vs: parsed dict of f5 virtual service. :param vs_state: State of created Avi VS object :param avi_config: dict for avi conversion :param snat_config: parsed source address translation dict :param user_ignore: Ignore config defined by user :param tenant_ref: Tenant for which config need to be converted :param cloud_name: cloud for which config need to be converted :param controller_version: AVI controller version :param merge_object_mapping: Flag to merge object :param sys_dict: Baseline dict :param vrf: vrf user input to put vrf ref in VS object :return: """ needs_review = False tenant, vs_name = conv_utils.get_tenant_ref(vs_name) tenant_name = tenant if not tenant_ref == 'admin': tenant = tenant_ref # Added prefix for objects if self.prefix: vs_name = '{}-{}'.format(self.prefix, vs_name) hash_profiles = avi_config.get('hash_algorithm', []) description = f5_vs.get("description", None) skipped = [key for key in f5_vs.keys() if key not in self.supported_attr] enabled = (vs_state == 'enable') if enabled: enabled = False if "disabled" in f5_vs.keys() else True profiles = f5_vs.get("profiles", {}) ssl_vs, ssl_pool = conv_utils.get_vs_ssl_profiles( profiles, avi_config, self.prefix, merge_object_mapping, sys_dict, f5_config) if (ssl_vs and len(ssl_vs) > 1) or (ssl_pool and len(ssl_pool)> 1): needs_review = True oc_prof = False for prof in profiles: prof_name = prof.split('/')[-1] if '/' in prof else prof if prof_name in avi_config.get('OneConnect', []): oc_prof = True enable_ssl = False if ssl_vs: enable_ssl = True app_prof_conf = conv_utils.get_vs_app_profiles( profiles, avi_config, tenant, self.prefix, oc_prof, enable_ssl, merge_object_mapping, sys_dict) app_prof = app_prof_conf.get('app_prof', None) f_host = app_prof_conf.get('f_host', None) realm = app_prof_conf.get('realm', None) app_pol_name = app_prof_conf.get('app_pol_name', None) if not app_prof: msg = ('Profile type not supported by Avi Skipping VS : %s' % vs_name) LOG.warning(msg) conv_utils.add_status_row('virtual', None, vs_name, final.STATUS_SKIPPED, msg) return None ntwk_prof = conv_utils.get_vs_ntwk_profiles( profiles, avi_config, self.prefix, merge_object_mapping, sys_dict) # If one connect profile is not assigned to f5 VS and avi app profile # assigned to VS has connection_multiplexing_enabled value True then # clone profile and make connection_multiplexing_enabled as False pool_ref = f5_vs.get("pool", None) app_name = conv_utils.get_name(app_prof[0]) app_prof_obj = [obj for obj in (sys_dict['ApplicationProfile'] + avi_config['ApplicationProfile']) if obj['name'] == app_name] cme = True app_prof_type = None if app_prof_obj: app_prof_type = app_prof_obj[0].get('type') if app_prof_type == 'APPLICATION_PROFILE_TYPE_HTTP': cme = app_prof_obj[0]['http_profile'].get( 'connection_multiplexing_enabled', False) if app_prof_obj and not (cme and oc_prof): # Check if already cloned profile present app_prof_cmd = [obj for obj in ( sys_dict['ApplicationProfile'] + avi_config['ApplicationProfile']) if obj['name'] == '%s-cmd' % app_name] if app_prof_cmd: app_name = app_prof_cmd[0]['name'] app_prof[0] = conv_utils.get_object_ref( app_name, 'applicationprofile', tenant=conv_utils.get_name(app_prof_cmd[0]['tenant_ref'])) else: app_prof_cmd = copy.deepcopy(app_prof_obj[0]) app_prof_cmd['name'] = '%s-cmd' % app_prof_cmd['name'] if 'http_profile' in app_prof_cmd: app_prof_cmd['http_profile'][ 'connection_multiplexing_enabled'] = False avi_config['ApplicationProfile'].append(app_prof_cmd) app_name = app_prof_cmd['name'] app_prof[0] = conv_utils.get_object_ref( app_name, 'applicationprofile', tenant=conv_utils.get_name(app_prof_cmd['tenant_ref'])) destination = f5_vs.get("destination", None) d_tenant, destination = conv_utils.get_tenant_ref(destination) # if destination is not present then skip vs. services_obj, ip_addr, vsvip_ref, vrf_ref = conv_utils.get_service_obj( destination, avi_config, enable_ssl, controller_version, tenant, cloud_name, self.prefix, vs_name, vrf) # Added check for same vip in same vrf if vsvip_ref == '': msg = "Skipped: Virtualservice %s has repeated vip not in " \ "different vrf" % vs_name LOG.debug(msg) conv_utils.add_status_row('virtual', None, vs_name, final.STATUS_SKIPPED, msg) return # Added Check for if port is no digit skip vs. if not services_obj and not ip_addr and not vsvip_ref: msg = "Skipped Virtualservice : %s" % vs_name LOG.debug(msg) conv_utils.add_status_row('virtual', None, vs_name, final.STATUS_SKIPPED, msg) return is_pool_group = False if pool_ref: p_tenant, pool_ref = conv_utils.get_tenant_ref(pool_ref) if not tenant_ref == 'admin': p_tenant = tenant_ref persist_ref = self.get_persist_ref(f5_vs) avi_persistence = avi_config['ApplicationPersistenceProfile'] syspersist = sys_dict['ApplicationPersistenceProfile'] persist_type = None if persist_ref: # Called tenant ref to get object name persist_ref = conv_utils.get_tenant_ref(persist_ref)[1] if self.prefix: persist_ref = '{}-{}'.format(self.prefix, persist_ref) persist_profile_objs = ( [ob for ob in syspersist if ob['name'] == merge_object_mapping['app_per_profile'].get( persist_ref)] or [obj for obj in avi_persistence if (obj["name"] == persist_ref or persist_ref in obj.get( "dup_of", []))]) persist_type = (persist_profile_objs[0]['persistence_type'] if persist_profile_objs else None) # Pool cloned if controller version < 17.1.6 or VS has non http # cookie persistence or app profile type is different and poolgroup # cloned pool_ref, is_pool_group = conv_utils.clone_pool_if_shared( pool_ref, avi_config, vs_name, tenant, p_tenant, persist_type, controller_version, app_prof[0], sys_dict, cloud_name=cloud_name, prefix=self.prefix) if ssl_pool: if is_pool_group: conv_utils.add_ssl_to_pool_group(avi_config, pool_ref, ssl_pool[0], tenant) conv_utils.remove_http_mon_from_pool_group( avi_config, pool_ref, tenant, sys_dict) else: conv_utils.add_ssl_to_pool(avi_config['Pool'], pool_ref, ssl_pool[0], tenant) conv_utils.remove_http_mon_from_pool( avi_config, pool_ref, tenant, sys_dict) else: # TODO Remove this once controller support this scenario. if is_pool_group: conv_utils.remove_https_mon_from_pool_group( avi_config, pool_ref, tenant, sys_dict) else: conv_utils.remove_https_mon_from_pool( avi_config, pool_ref, tenant, sys_dict) persist_type = None if persist_ref: if is_pool_group: pool_updated, persist_type = \ conv_utils.update_pool_group_for_persist( avi_config, pool_ref, persist_ref, hash_profiles, avi_persistence, tenant, merge_object_mapping, syspersist, app_prof_type) else: pool_updated, persist_type = \ conv_utils.update_pool_for_persist( avi_config['Pool'], pool_ref, persist_ref, hash_profiles, avi_persistence, tenant, merge_object_mapping, syspersist, app_prof_type) if not pool_updated: skipped.append("persist") LOG.warning( "persist profile %s not found for vs:%s" % (persist_ref, vs_name)) if oc_prof and not ssl_vs and persist_type == \ 'PERSISTENCE_TYPE_TLS': msg = ("Skipped VS : '%s' Secure persistence is applicable only" " if SSL is enabled for Virtual Service" % vs_name) LOG.warning(msg) conv_utils.add_status_row('virtual', None, vs_name, final.STATUS_SKIPPED, msg) return if f_host: conv_utils.update_pool_for_fallback( f_host, avi_config['Pool'], pool_ref) ip_addr = ip_addr.strip() matches = re.findall('^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$', ip_addr) if not matches or ip_addr == '0.0.0.0': LOG.warning('Avi does not support IPv6 : %s. ' 'Generated random ipv4 for vs: %s' % (ip_addr, vs_name)) vs_name += '-needs-ipv6-ip' ip_addr = ".".join(map(str, ( random.randint(0, 255) for _ in range(4)))) # VIP object for virtual service vip = { 'ip_address': { 'addr': ip_addr, 'type': 'V4' }, 'vip_id': '1' } vs_obj = { 'name': vs_name, 'description': description, 'type': 'VS_TYPE_NORMAL', 'enabled': enabled, 'cloud_ref': conv_utils.get_object_ref( cloud_name, 'cloud', tenant=tenant), 'services': services_obj, 'application_profile_ref': app_prof[0], 'vs_datascripts': [], 'tenant_ref': conv_utils.get_object_ref(tenant, 'tenant') } if vrf: vrf_ref = conv_utils.get_object_ref(vrf, 'vrfcontext', tenant=tenant_name, cloud_name=cloud_name) if vrf_ref: vs_obj['vrf_context_ref'] = vrf_ref # Added code for assigning VS's vrf ref to poolgroup/pool having no # vrf ref if is_pool_group: conv_utils.set_pool_group_vrf(pool_ref, vrf_ref, avi_config) elif pool_ref: conv_utils.set_pool_vrf(pool_ref, vrf_ref, avi_config) else: # Added code for removing vrf ref from poolgroup/pool if VS is not # having vrf ref if is_pool_group: conv_utils.remove_pool_group_vrf(pool_ref, avi_config) elif pool_ref: conv_utils.remove_pool_vrf(pool_ref, avi_config) if parse_version(controller_version) >= parse_version('17.1'): vs_obj['vip'] = [vip] vs_obj['vsvip_ref'] = vsvip_ref else: vs_obj['ip_address'] = vip['ip_address'] # Policy tracking starts from here vs_policies = [app_pol_name] if app_pol_name else [] vs_ds_rules = None vs_ds = list() nw_policy = None converted_rules = list() if 'rules' in f5_vs: if isinstance(f5_vs['rules'], basestring): vs_ds_rules = [conv_utils.get_tenant_ref(f5_vs['rules'])[1]] else: vs_ds_rules = [conv_utils.get_tenant_ref(name)[1] for name in f5_vs['rules'].keys()] vs_ds, req_policies, nw_policy, converted_rules = ( conv_utils.convert_irules( vs_ds_rules, self.rule_config, avi_config, self.prefix, vs_name, tenant)) vs_policies = vs_policies + req_policies if vs_ds: vs_datascripts = [] index = 1 for ds in vs_ds: vs_datascripts.append( { "index": index, "vs_datascript_set_ref": conv_utils.get_object_ref( ds, 'vsdatascriptset', tenant=tenant) } ) index += 1 vs_obj['vs_datascripts'] = vs_datascripts if 'policies' in f5_vs: if isinstance(f5_vs['policies'], basestring): vs_policies.extend(['%s-%s' % ( self.prefix, conv_utils.get_tenant_ref( f5_vs['policies'])[1]) if self.prefix else conv_utils.get_tenant_ref( f5_vs['policies'])[1]]) else: vs_policies.extend(['%s-%s' % ( self.prefix, conv_utils.get_tenant_ref(name)[1]) if self.prefix else conv_utils.get_tenant_ref( name)[1] for name in f5_vs['policies'].keys()]) if app_prof_obj and 'HTTPPolicySet' in app_prof_obj[0]: vs_policies.append(app_prof_obj[0]['HTTPPolicySet']) if vs_policies: self.get_policy_vs(vs_policies, avi_config, vs_name, tenant, cloud_name, vs_obj) p_ref = None if is_pool_group: p_ref = conv_utils.get_object_ref( pool_ref, 'poolgroup', tenant=p_tenant) elif pool_ref: p_ref = conv_utils.get_object_ref( pool_ref, 'pool', tenant=p_tenant) if p_ref and used_pools.get(p_ref): not_same = [pol_obj for pol_obj in used_pools[p_ref] if pol_obj not in vs_policies] if not_same: if is_pool_group: LOG.debug('Pool group %s attached to vs %s is shared ' 'with policy %s of another vs, hence cloned', pool_ref, vs_name, str(not_same)) pool_ref = conv_utils.clone_pool_group( pool_ref, vs_name, avi_config, False, p_tenant, cloud_name=cloud_name) else: LOG.debug('Pool %s attached to vs %s is shared with ' 'policy %s of another vs, hence cloned', pool_ref, vs_name, str(not_same)) pool_ref = conv_utils.clone_pool( pool_ref, vs_name, avi_config['Pool'], False, p_tenant) if is_pool_group: vs_obj['pool_group_ref'] = conv_utils.get_object_ref( pool_ref, 'poolgroup', tenant=tenant, cloud_name=cloud_name) elif pool_ref: vs_obj['pool_ref'] = conv_utils.get_object_ref( pool_ref, 'pool', tenant=tenant, cloud_name=cloud_name) # app prof ref is not used inside the below method call self.convert_translate_port(avi_config, f5_vs, app_prof[0], pool_ref, sys_dict) conn_limit = int(f5_vs.get(self.connection_limit, '0')) if conn_limit > 0: vs_obj["performance_limits"] = { "max_concurrent_connections": conn_limit } rate_limit = int(f5_vs.get('rate-limit', '0')) if rate_limit > 0: vs_obj["connections_rate_limit"] = { "count": rate_limit } if realm: vs_obj['client_auth'] = realm source = f5_vs.get('source', '0.0.0.0/0') if '%' in source: s_parts = source.split('%') elif '/' in source: s_parts = source.split('/') else: s_parts = [source] if not s_parts[0] == '0.0.0.0': parts = source.split('/') if '%' in parts[0]: parts[0] = parts[0].split('%')[0] mask = 24 if len(parts) > 1: mask = parts[1] policy_name = ('vs-%s-ns' % vs_name) if self.prefix: policy_name = '%s-%s' % (self.prefix, policy_name) policy = conv_utils.create_network_security_rule( policy_name, parts[0], mask, tenant) if nw_policy: old_policy = [obj for obj in avi_config['NetworkSecurityPolicy'] if obj['name'] == nw_policy][0] policy['rules'][0]['index'] = 2 policy['rules'][0]['name'] = 'Rule 2' old_policy['rules'].append(policy['rules'][0]) else: avi_config['NetworkSecurityPolicy'].append(policy) nw_policy = policy_name if nw_policy: vs_obj['network_security_policy_ref'] = conv_utils.get_object_ref( nw_policy, 'networksecuritypolicy', tenant=tenant) # Checking snat conversion flag and snat info for creating # snat ip object snat = f5_vs.get("source-address-translation", {}) snat_pool_name = snat.get("pool", f5_vs.get("snatpool", None)) snat_pool = snat_config.pop(snat_pool_name, None) if snat_pool: if self.con_snatpool: LOG.debug("Converting the snat as input flag and snat " "information is set") snat_list = conv_utils.get_snat_list_for_vs(snat_pool) if len(snat_list) > 32: vs_obj["snat_ip"] = snat_list[0:32] LOG.warning('Ignore the snat IPs, its count is beyond 32 ' 'for vs : %s' % vs_name) else: vs_obj["snat_ip"] = snat_list conv_status = {'status': final.STATUS_SUCCESSFUL} message = 'Mapped indirectly to VS -> SNAT IP Address' conv_utils.add_conv_status('snatpool', '', snat_pool_name, conv_status, message) else: msg = ("Skipped: snat conversion as input flag is not set" " for vs : %s" % vs_name) LOG.debug(msg) conv_status = {'status': final.STATUS_SKIPPED} skipped.append("source-address-translation" if f5_vs.get( "source-address-translation") else "snatpool" if f5_vs.get( "snatpool") else None) conv_utils.add_conv_status('snatpool', '', snat_pool_name, conv_status, msg) if ntwk_prof: vs_obj['network_profile_ref'] = ntwk_prof[0] if enable_ssl: vs_obj['ssl_profile_ref'] = ssl_vs[0]["profile"] if ssl_vs[0]["cert"]: vs_obj['ssl_key_and_certificate_refs'] = [ssl_vs[0]["cert"]] if ssl_vs[0]["pki"] and app_name != "http": app_profiles = [obj for obj in ( sys_dict['ApplicationProfile'] + avi_config['ApplicationProfile']) if obj['name'] == app_name] if app_profiles[0]["type"] == \ 'APPLICATION_PROFILE_TYPE_HTTP': app_profiles[0]["http_profile"][ "ssl_client_certificate_mode"] = ssl_vs[0]["mode"] app_profiles[0]["http_profile"]["pki_profile_ref"] = \ ssl_vs[0]["pki"] # Added code to skipped L4 VS if pool or pool group not present if vs_obj['application_profile_ref']: application_profile_obj = \ [obj for obj in (sys_dict['ApplicationProfile'] + avi_config['ApplicationProfile']) if obj['name'] == app_name] if application_profile_obj and application_profile_obj[0]['type'] \ == 'APPLICATION_PROFILE_TYPE_L4': if not vs_obj.get('pool_ref', vs_obj.get('pool_group_ref')): msg = ("Failed to convert L4 VS dont have pool or pool " "group ref: %s" % vs_name) LOG.debug(msg) conv_utils.add_status_row('virtual', None, vs_name, final.STATUS_SKIPPED, msg) return for attr in self.ignore_for_value: ignore_val = self.ignore_for_value[attr] actual_val = f5_vs.get(attr, None) if not actual_val: continue if isinstance(ignore_val, str) and actual_val == ignore_val: skipped.remove(attr) elif isinstance(ignore_val, list) and actual_val in ignore_val: skipped.remove(attr) conv_status = dict() conv_status['user_ignore'] = [val for val in skipped if val in user_ignore] if vs_ds_rules: vs_ds.append('_sys_https_redirect') skipped_rules = [rule for rule in vs_ds_rules if rule not in converted_rules] if skipped_rules: skipped.append('rules: %s' % skipped_rules) conv_status['na_list'] = [val for val in skipped if val in self.vs_na_attr] skipped = [attr for attr in skipped if attr not in self.vs_na_attr] skipped = [attr for attr in skipped if attr not in user_ignore] conv_status['skipped'] = skipped status = final.STATUS_SUCCESSFUL if skipped: status = final.STATUS_PARTIAL conv_status['status'] = status review_flag = 'Yes' if needs_review else None conv_utils.add_conv_status('virtual', None, vs_name, conv_status, vs_obj, review_flag) return vs_obj
def convert_vs(self, vs_name, f5_vs, vs_state, avi_config, snat_config, user_ignore, tenant_ref, cloud_name, controller_version, merge_object_mapping, sys_dict, f5_config, vrf=None): """ :param vs_name: name of virtual service. :param f5_vs: parsed dict of f5 virtual service. :param vs_state: State of created Avi VS object :param avi_config: dict for avi conversion :param snat_config: parsed source address translation dict :param user_ignore: Ignore config defined by user :param tenant_ref: Tenant for which config need to be converted :param cloud_name: cloud for which config need to be converted :param controller_version: AVI controller version :param merge_object_mapping: Flag to merge object :param sys_dict: Baseline dict :param vrf: vrf user input to put vrf ref in VS object :return: """ needs_review = False tenant, vs_name = conv_utils.get_tenant_ref(vs_name) tenant_name = tenant if not tenant_ref == 'admin': tenant = tenant_ref # Added prefix for objects if self.prefix: vs_name = '{}-{}'.format(self.prefix, vs_name) hash_profiles = avi_config.get('hash_algorithm', []) description = f5_vs.get("description", None) skipped = [key for key in f5_vs.keys() if key not in self.supported_attr] enabled = (vs_state == 'enable') if enabled: enabled = False if "disabled" in f5_vs.keys() else True profiles = f5_vs.get("profiles", {}) ssl_vs, ssl_pool = conv_utils.get_vs_ssl_profiles( profiles, avi_config, self.prefix, merge_object_mapping, sys_dict, f5_config) if (ssl_vs and len(ssl_vs) > 1) or (ssl_pool and len(ssl_pool)> 1): needs_review = True oc_prof = False for prof in profiles: prof_name = prof.split('/')[-1] if '/' in prof else prof if prof_name in avi_config.get('OneConnect', []): oc_prof = True enable_ssl = False if ssl_vs: enable_ssl = True app_prof_conf = conv_utils.get_vs_app_profiles( profiles, avi_config, tenant, self.prefix, oc_prof, enable_ssl, merge_object_mapping, sys_dict) app_prof = app_prof_conf.get('app_prof', None) f_host = app_prof_conf.get('f_host', None) realm = app_prof_conf.get('realm', None) app_pol_name = app_prof_conf.get('app_pol_name', None) if not app_prof: msg = ('Profile type not supported by Avi Skipping VS : %s' % vs_name) LOG.warning(msg) conv_utils.add_status_row('virtual', None, vs_name, final.STATUS_SKIPPED, msg) return None ntwk_prof = conv_utils.get_vs_ntwk_profiles( profiles, avi_config, self.prefix, merge_object_mapping, sys_dict) # If one connect profile is not assigned to f5 VS and avi app profile # assigned to VS has connection_multiplexing_enabled value True then # clone profile and make connection_multiplexing_enabled as False pool_ref = f5_vs.get("pool", None) app_name = conv_utils.get_name(app_prof[0]) app_prof_obj = [obj for obj in (sys_dict['ApplicationProfile'] + avi_config['ApplicationProfile']) if obj['name'] == app_name] cme = True app_prof_type = None if app_prof_obj: app_prof_type = app_prof_obj[0].get('type') else: if app_name == 'System-L4-Application': app_prof_type = 'APPLICATION_PROFILE_TYPE_L4' elif app_name in ['System-HTTP', 'System-Secure-HTTP']: app_prof_type = 'APPLICATION_PROFILE_TYPE_HTTP' elif app_name == 'System-SSL-Application': app_prof_type = 'APPLICATION_PROFILE_TYPE_SSL' if app_prof_type == 'APPLICATION_PROFILE_TYPE_HTTP': cme = app_prof_obj[0]['http_profile'].get( 'connection_multiplexing_enabled', False) if app_prof_obj and not (cme and oc_prof): # Check if already cloned profile present app_prof_cmd = [obj for obj in ( sys_dict['ApplicationProfile'] + avi_config['ApplicationProfile']) if obj['name'] == '%s-cmd' % app_name] if app_prof_cmd: app_name = app_prof_cmd[0]['name'] app_prof[0] = conv_utils.get_object_ref( app_name, 'applicationprofile', tenant=conv_utils.get_name(app_prof_cmd[0]['tenant_ref'])) else: app_prof_cmd = copy.deepcopy(app_prof_obj[0]) app_prof_cmd['name'] = '%s-cmd' % app_prof_cmd['name'] if 'http_profile' in app_prof_cmd: app_prof_cmd['http_profile'][ 'connection_multiplexing_enabled'] = False avi_config['ApplicationProfile'].append(app_prof_cmd) app_name = app_prof_cmd['name'] app_prof[0] = conv_utils.get_object_ref( app_name, 'applicationprofile', tenant=conv_utils.get_name(app_prof_cmd['tenant_ref'])) destination = f5_vs.get("destination", None) d_tenant, destination = conv_utils.get_tenant_ref(destination) # if destination is not present then skip vs. services_obj, ip_addr, vsvip_ref, vrf_ref = conv_utils.get_service_obj( destination, avi_config, enable_ssl, controller_version, tenant, cloud_name, self.prefix, vs_name, vrf) # Added check for same vip in same vrf if vsvip_ref == '': msg = "Skipped: Virtualservice %s has repeated vip not in " \ "different vrf" % vs_name LOG.debug(msg) conv_utils.add_status_row('virtual', None, vs_name, final.STATUS_SKIPPED, msg) return # Added Check for if port is no digit skip vs. if not services_obj and not ip_addr and not vsvip_ref: msg = "Skipped Virtualservice : %s" % vs_name LOG.debug(msg) conv_utils.add_status_row('virtual', None, vs_name, final.STATUS_SKIPPED, msg) return is_pool_group = False if pool_ref: p_tenant, pool_ref = conv_utils.get_tenant_ref(pool_ref) if not tenant_ref == 'admin': p_tenant = tenant_ref persist_ref = self.get_persist_ref(f5_vs) avi_persistence = avi_config['ApplicationPersistenceProfile'] syspersist = sys_dict['ApplicationPersistenceProfile'] persist_type = None if persist_ref: # Called tenant ref to get object name persist_ref = conv_utils.get_tenant_ref(persist_ref)[1] if self.prefix: persist_ref = '{}-{}'.format(self.prefix, persist_ref) persist_profile_objs = ( [ob for ob in syspersist if ob['name'] == merge_object_mapping['app_per_profile'].get( persist_ref)] or [obj for obj in avi_persistence if (obj["name"] == persist_ref or persist_ref in obj.get( "dup_of", []))]) persist_type = (persist_profile_objs[0]['persistence_type'] if persist_profile_objs else None) # Pool cloned if controller version < 17.1.6 or VS has non http # cookie persistence or app profile type is different and poolgroup # cloned pool_ref, is_pool_group = conv_utils.clone_pool_if_shared( pool_ref, avi_config, vs_name, tenant, p_tenant, persist_type, controller_version, app_prof[0], sys_dict, cloud_name=cloud_name, prefix=self.prefix) if ssl_pool: if is_pool_group: conv_utils.add_ssl_to_pool_group(avi_config, pool_ref, ssl_pool[0], tenant) conv_utils.remove_http_mon_from_pool_group( avi_config, pool_ref, tenant, sys_dict) else: conv_utils.add_ssl_to_pool(avi_config['Pool'], pool_ref, ssl_pool[0], tenant) conv_utils.remove_http_mon_from_pool( avi_config, pool_ref, tenant, sys_dict) else: # TODO Remove this once controller support this scenario. if is_pool_group: conv_utils.remove_https_mon_from_pool_group( avi_config, pool_ref, tenant, sys_dict) else: conv_utils.remove_https_mon_from_pool( avi_config, pool_ref, tenant, sys_dict) persist_type = None if persist_ref: if is_pool_group: pool_updated, persist_type = \ conv_utils.update_pool_group_for_persist( avi_config, pool_ref, persist_ref, hash_profiles, avi_persistence, tenant, merge_object_mapping, syspersist, app_prof_type) else: pool_updated, persist_type = \ conv_utils.update_pool_for_persist( avi_config['Pool'], pool_ref, persist_ref, hash_profiles, avi_persistence, tenant, merge_object_mapping, syspersist, app_prof_type) if not pool_updated: skipped.append("persist") LOG.warning( "persist profile %s not found for vs:%s" % (persist_ref, vs_name)) if (oc_prof and not ssl_vs and persist_type == 'PERSISTENCE_TYPE_TLS' or persist_type == 'PERSISTENCE_TYPE_TLS' and not enable_ssl): msg = ("Skipped VS : '%s' Secure persistence is applicable only" " if SSL is enabled for Virtual Service" % vs_name) LOG.warning(msg) conv_utils.add_status_row('virtual', None, vs_name, final.STATUS_SKIPPED, msg) return # TODO: Followiong condition to be removed after controller adds # TODO: support for PERSISTENCE_TYPE_TLS for SSL VS elif (persist_type == 'PERSISTENCE_TYPE_TLS' and app_prof_type == 'APPLICATION_PROFILE_TYPE_SSL'): msg = ("Skipped VS : '%s' Only client-ip persistence is " "applicable for SSL VS" % vs_name) LOG.warning(msg) conv_utils.add_status_row('virtual', None, vs_name, final.STATUS_SKIPPED, msg) return if f_host: conv_utils.update_pool_for_fallback( f_host, avi_config['Pool'], pool_ref) ip_addr = ip_addr.strip() matches = re.findall('^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$', ip_addr) if not matches or ip_addr == '0.0.0.0': LOG.warning('Avi does not support IPv6 : %s. ' 'Generated random ipv4 for vs: %s' % (ip_addr, vs_name)) vs_name += '-needs-ipv6-ip' ip_addr = ".".join(map(str, ( random.randint(0, 255) for _ in range(4)))) # VIP object for virtual service vip = { 'ip_address': { 'addr': ip_addr, 'type': 'V4' }, 'vip_id': '1' } vs_obj = { 'name': vs_name, 'description': description, 'type': 'VS_TYPE_NORMAL', 'enabled': True, 'traffic_enabled': enabled, 'cloud_ref': conv_utils.get_object_ref( cloud_name, 'cloud', tenant=tenant), 'services': services_obj, 'application_profile_ref': app_prof[0], 'vs_datascripts': [], 'tenant_ref': conv_utils.get_object_ref(tenant, 'tenant') } if vrf: vrf_ref = conv_utils.get_object_ref(vrf, 'vrfcontext', tenant=tenant_name, cloud_name=cloud_name) if vrf_ref: vs_obj['vrf_context_ref'] = vrf_ref # Added code for assigning VS's vrf ref to poolgroup/pool having no # vrf ref if is_pool_group: conv_utils.set_pool_group_vrf(pool_ref, vrf_ref, avi_config) elif pool_ref: conv_utils.set_pool_vrf(pool_ref, vrf_ref, avi_config) else: # Added code for removing vrf ref from poolgroup/pool if VS is not # having vrf ref if is_pool_group: conv_utils.remove_pool_group_vrf(pool_ref, avi_config) elif pool_ref: conv_utils.remove_pool_vrf(pool_ref, avi_config) if parse_version(controller_version) >= parse_version('17.1'): vs_obj['vip'] = [vip] vs_obj['vsvip_ref'] = vsvip_ref else: vs_obj['ip_address'] = vip['ip_address'] # Policy tracking starts from here vs_policies = [app_pol_name] if app_pol_name else [] vs_ds_rules = None vs_ds = list() nw_policy = None converted_rules = list() if 'rules' in f5_vs: if isinstance(f5_vs['rules'], basestring): vs_ds_rules = [conv_utils.get_tenant_ref(f5_vs['rules'])[1]] else: vs_ds_rules = [conv_utils.get_tenant_ref(name)[1] for name in f5_vs['rules'].keys()] vs_ds, req_policies, nw_policy, converted_rules = ( conv_utils.convert_irules( vs_ds_rules, self.rule_config, avi_config, self.prefix, vs_name, tenant)) vs_policies = vs_policies + req_policies if vs_ds: vs_datascripts = [] index = 1 for ds in vs_ds: vs_datascripts.append( { "index": index, "vs_datascript_set_ref": conv_utils.get_object_ref( ds, 'vsdatascriptset', tenant=tenant) } ) index += 1 vs_obj['vs_datascripts'] = vs_datascripts if 'policies' in f5_vs: if isinstance(f5_vs['policies'], basestring): vs_policies.extend(['%s-%s' % ( self.prefix, conv_utils.get_tenant_ref( f5_vs['policies'])[1]) if self.prefix else conv_utils.get_tenant_ref( f5_vs['policies'])[1]]) else: vs_policies.extend(['%s-%s' % ( self.prefix, conv_utils.get_tenant_ref(name)[1]) if self.prefix else conv_utils.get_tenant_ref( name)[1] for name in f5_vs['policies'].keys()]) if app_prof_obj and 'HTTPPolicySet' in app_prof_obj[0]: vs_policies.append(app_prof_obj[0]['HTTPPolicySet']) if vs_policies: self.get_policy_vs(vs_policies, avi_config, vs_name, tenant, cloud_name, vs_obj) p_ref = None if is_pool_group: p_ref = conv_utils.get_object_ref( pool_ref, 'poolgroup', tenant=p_tenant) elif pool_ref: p_ref = conv_utils.get_object_ref( pool_ref, 'pool', tenant=p_tenant) if p_ref and used_pools.get(p_ref): not_same = [pol_obj for pol_obj in used_pools[p_ref] if pol_obj not in vs_policies] if not_same: if is_pool_group: LOG.debug('Pool group %s attached to vs %s is shared ' 'with policy %s of another vs, hence cloned', pool_ref, vs_name, str(not_same)) pool_ref = conv_utils.clone_pool_group( pool_ref, vs_name, avi_config, False, p_tenant, cloud_name=cloud_name) else: LOG.debug('Pool %s attached to vs %s is shared with ' 'policy %s of another vs, hence cloned', pool_ref, vs_name, str(not_same)) pool_ref = conv_utils.clone_pool( pool_ref, vs_name, avi_config['Pool'], False, p_tenant) if is_pool_group: vs_obj['pool_group_ref'] = conv_utils.get_object_ref( pool_ref, 'poolgroup', tenant=tenant, cloud_name=cloud_name) elif pool_ref: vs_obj['pool_ref'] = conv_utils.get_object_ref( pool_ref, 'pool', tenant=tenant, cloud_name=cloud_name) # app prof ref is not used inside the below method call self.convert_translate_port(avi_config, f5_vs, app_prof[0], pool_ref, sys_dict) conn_limit = int(f5_vs.get(self.connection_limit, '0')) if conn_limit > 0: vs_obj["performance_limits"] = { "max_concurrent_connections": conn_limit } rate_limit = int(f5_vs.get('rate-limit', '0')) if rate_limit > 0: vs_obj["connections_rate_limit"] = { "count": rate_limit, 'explicit_tracking': False, 'period': 1, 'action': { 'status_code': 'HTTP_LOCAL_RESPONSE_STATUS_CODE_429', 'type': "RL_ACTION_NONE" }, 'burst_sz': 0, 'fine_grain': False } if realm: vs_obj['client_auth'] = realm source = f5_vs.get('source', '0.0.0.0/0') if '%' in source: s_parts = source.split('%') elif '/' in source: s_parts = source.split('/') else: s_parts = [source] if not s_parts[0] == '0.0.0.0': parts = source.split('/') if '%' in parts[0]: parts[0] = parts[0].split('%')[0] mask = 24 if len(parts) > 1: mask = parts[1] policy_name = ('vs-%s-ns' % vs_name) if self.prefix: policy_name = '%s-%s' % (self.prefix, policy_name) policy = conv_utils.create_network_security_rule( policy_name, parts[0], mask, tenant) if nw_policy: old_policy = [obj for obj in avi_config['NetworkSecurityPolicy'] if obj['name'] == nw_policy][0] policy['rules'][0]['index'] = 2 policy['rules'][0]['name'] = 'Rule 2' old_policy['rules'].append(policy['rules'][0]) else: avi_config['NetworkSecurityPolicy'].append(policy) nw_policy = policy_name if nw_policy: vs_obj['network_security_policy_ref'] = conv_utils.get_object_ref( nw_policy, 'networksecuritypolicy', tenant=tenant) # Checking snat conversion flag and snat info for creating # snat ip object snat = f5_vs.get("source-address-translation", {}) snat_pool_name = snat.get("pool", f5_vs.get("snatpool", None)) snat_pool = snat_config.pop(snat_pool_name, None) if snat_pool: if self.con_snatpool: LOG.debug("Converting the snat as input flag and snat " "information is set") snat_list = conv_utils.get_snat_list_for_vs(snat_pool) if len(snat_list) > 32: vs_obj["snat_ip"] = snat_list[0:32] LOG.warning('Ignore the snat IPs, its count is beyond 32 ' 'for vs : %s' % vs_name) else: vs_obj["snat_ip"] = snat_list conv_status = {'status': final.STATUS_SUCCESSFUL} message = 'Mapped indirectly to VS -> SNAT IP Address' conv_utils.add_conv_status('snatpool', '', snat_pool_name, conv_status, message) else: msg = ("Skipped: snat conversion as input flag is not set" " for vs : %s" % vs_name) LOG.debug(msg) conv_status = {'status': final.STATUS_SKIPPED} skipped.append("source-address-translation" if f5_vs.get( "source-address-translation") else "snatpool" if f5_vs.get( "snatpool") else None) conv_utils.add_conv_status('snatpool', '', snat_pool_name, conv_status, msg) if ntwk_prof: vs_obj['network_profile_ref'] = ntwk_prof[0] if enable_ssl: vs_obj['ssl_profile_ref'] = ssl_vs[0]["profile"] if ssl_vs[0]["cert"]: vs_obj['ssl_key_and_certificate_refs'] = [ssl_vs[0]["cert"]] if ssl_vs[0]["pki"] and app_name != "http": app_profiles = [obj for obj in ( sys_dict['ApplicationProfile'] + avi_config['ApplicationProfile']) if obj['name'] == app_name] if app_profiles[0]["type"] == \ 'APPLICATION_PROFILE_TYPE_HTTP': app_profiles[0]["http_profile"][ "ssl_client_certificate_mode"] = ssl_vs[0]["mode"] app_profiles[0]["http_profile"]["pki_profile_ref"] = \ ssl_vs[0]["pki"] # Added code to skipped L4 VS if pool or pool group not present if vs_obj['application_profile_ref']: application_profile_obj = \ [obj for obj in (sys_dict['ApplicationProfile'] + avi_config['ApplicationProfile']) if obj['name'] == app_name] if application_profile_obj and application_profile_obj[0]['type'] \ == 'APPLICATION_PROFILE_TYPE_L4': if not vs_obj.get('pool_ref', vs_obj.get('pool_group_ref')): msg = ("Failed to convert L4 VS dont have pool or pool " "group ref: %s" % vs_name) LOG.debug(msg) conv_utils.add_status_row('virtual', None, vs_name, final.STATUS_SKIPPED, msg) return for attr in self.ignore_for_value: ignore_val = self.ignore_for_value[attr] actual_val = f5_vs.get(attr, None) if not actual_val: continue if isinstance(ignore_val, str) and actual_val == ignore_val: skipped.remove(attr) elif isinstance(ignore_val, list) and actual_val in ignore_val: skipped.remove(attr) conv_status = dict() conv_status['user_ignore'] = [val for val in skipped if val in user_ignore] if vs_ds_rules: vs_ds.append('_sys_https_redirect') skipped_rules = [rule for rule in vs_ds_rules if rule not in converted_rules] if skipped_rules: skipped.append('rules: %s' % skipped_rules) conv_status['na_list'] = [val for val in skipped if val in self.vs_na_attr] skipped = [attr for attr in skipped if attr not in self.vs_na_attr] skipped = [attr for attr in skipped if attr not in user_ignore] conv_status['skipped'] = skipped status = final.STATUS_SUCCESSFUL if skipped: status = final.STATUS_PARTIAL conv_status['status'] = status review_flag = 'Yes' if needs_review else None conv_utils.add_conv_status('virtual', None, vs_name, conv_status, vs_obj, review_flag) return vs_obj