+#!/usr/bin/env python
+
import json
import logging
import os
# set the openstack cloud access credentials here
oom_mode = True
+ #############################################################################################
+ # set the gra_api flag
+ # Mustn't be set to True until Frankfurt DGs are updated for GRA-API infrastructure
+ gra_api_flag= False
+
###########################
# set Openstack credentials
# CHANGEME part
'--os-username': 'kxi',
'--os-user-domain-id': 'default',
'--os-project-domain-id': 'default',
- '--os-tenant-id': 'bc43d50ffcb84750bac0c1707a9a765b' if oom_mode else '1e097c6713e74fd7ac8e4295e605ee1e',
+ '--os-tenant-id': '712b6016580e410b9abfec9ca34953ce' if oom_mode else '1e097c6713e74fd7ac8e4295e605ee1e',
'--os-region-name': 'RegionOne',
'--os-password': 'n3JhGMGuDzD8',
- '--os-project-domain-name': 'Integration-SB-03' if oom_mode else 'Integration-SB-07',
+ '--os-project-domain-name': 'Integration-Release-Daily' if oom_mode else 'Integration-SB-07',
'--os-identity-api-version': '3'
}
# set oam and public network which must exist in openstack before deployment
# CHANGEME part
common_preload_config = {
- 'oam_onap_net': 'oam_network_2No2' if oom_mode else 'oam_onap_lAky',
- 'oam_onap_subnet': 'oam_network_2No2' if oom_mode else 'oam_onap_lAky',
+ 'oam_onap_net': 'oam_network_exxC' if oom_mode else 'oam_onap_lAky',
+ 'oam_onap_subnet': 'oam_network_exxC' if oom_mode else 'oam_onap_lAky',
'public_net': 'external',
'public_net_id': '971040b2-7059-49dc-b220-4fab50cb2ad4'
}
#############################################################################
- # set name of sdnc controller pod, prefix is taken from helm environment name
+ # Set name of Onap's k8s namespace and sdnc controller pod
# CHANGEME part
- sdnc_controller_pod = 'dev-sdnc-sdnc-0'
+ onap_namespace = 'onap'
+ onap_environment = 'dev'
+ sdnc_controller_pod = '-'.join([onap_environment, 'sdnc-sdnc-0'])
template_variable_symbol = '${'
cpe_vm_prefix = 'zdcpe'
self.vgw_VfModuleModelInvariantUuid = '26d6a718-17b2-4ba8-8691-c44343b2ecd2'
# OOM: this is the address that the brg and bng will nat for sdnc access - 10.0.0.x address of k8 host for sdnc-0 container
- self.sdnc_oam_ip = self.get_pod_node_oam_ip('sdnc-sdnc-0')
- # OOM: this is a k8s host external IP, e.g. oom-k8s-01 IP
- self.oom_so_sdnc_aai_ip = self.get_pod_node_public_ip('sdnc-sdnc-0')
+ self.sdnc_oam_ip = self.get_pod_node_oam_ip(self.sdnc_controller_pod)
+ # OOM: this is a k8s host external IP, e.g. oom-k8s-01 IP
+ self.oom_so_sdnc_aai_ip = self.get_pod_node_public_ip(self.sdnc_controller_pod)
# OOM: this is a k8s host external IP, e.g. oom-k8s-01 IP
self.oom_dcae_ves_collector = self.oom_so_sdnc_aai_ip
# OOM: this is a k8s host external IP, e.g. oom-k8s-01 IP
self.mr_ip_addr = self.oom_so_sdnc_aai_ip
self.mr_ip_port = '30227'
self.so_nbi_port = '30277' if self.oom_mode else '8080'
- self.sdnc_preloading_port = '30202' if self.oom_mode else '8282'
+ self.sdnc_preloading_port = '30267' if self.oom_mode else '8282'
self.aai_query_port = '30233' if self.oom_mode else '8443'
self.sniro_port = '30288' if self.oom_mode else '8080'
- self.host_names = ['sdc', 'so', 'sdnc', 'robot', 'aai-inst1', self.dcae_ves_collector_name]
+ self.host_names = ['sdc', 'so', 'sdnc', 'robot', 'aai-inst1', self.dcae_ves_collector_name, 'mariadb-galera']
if extra_host_names:
self.host_names.extend(extra_host_names)
# get IP addresses
#############################################################################################
# SDC urls
- self.sdc_be_port = '30205'
+ self.sdc_be_port = '30204'
self.sdc_be_request_userpass = 'vid', 'Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U'
self.sdc_be_request_headers = {'X-ECOMP-InstanceID': 'VID'}
- self.sdc_be_url_prefix = 'http://' + self.hosts['sdc'] + ':' + self.sdc_be_port
+ self.sdc_be_url_prefix = 'https://' + self.hosts['sdc'] + ':' + self.sdc_be_port
self.sdc_service_list_url = self.sdc_be_url_prefix + '/sdc/v1/catalog/services'
- self.sdc_fe_port = '30206'
+ self.sdc_fe_port = '30207'
self.sdc_fe_request_userpass = 'beep', 'boop'
self.sdc_fe_request_headers = {'USER_ID': 'demo', 'Content-Type': 'application/json'}
- self.sdc_fe_url_prefix = 'http://' + self.hosts['sdc'] + ':' + self.sdc_fe_port
+ self.sdc_fe_url_prefix = 'https://' + self.hosts['sdc'] + ':' + self.sdc_fe_port
self.sdc_get_category_list_url = self.sdc_fe_url_prefix + '/sdc1/feProxy/rest/v1/categories'
self.sdc_create_allotted_resource_subcategory_url = self.sdc_fe_url_prefix + '/sdc1/feProxy/rest/v1/category/resources/resourceNewCategory.allotted%20resource/subCategory'
self.sdnc_db_name = 'sdnctl'
self.sdnc_db_user = 'sdnctl'
self.sdnc_db_pass = 'gamma'
- self.sdnc_db_port = '32774'
+ self.sdnc_db_port = self.get_k8s_service_endpoint_info('mariadb-galera','port') if self.oom_mode else '3306'
self.sdnc_headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
- self.sdnc_preload_network_url = 'http://' + self.hosts['sdnc'] + \
+ self.sdnc_preload_network_url = 'https://' + self.hosts['sdnc'] + \
':' + self.sdnc_preloading_port + '/restconf/operations/VNF-API:preload-network-topology-operation'
- self.sdnc_preload_vnf_url = 'http://' + self.hosts['sdnc'] + \
+ self.sdnc_preload_network_gra_url = 'https://' + self.hosts['sdnc'] + \
+ ':' + self.sdnc_preloading_port + '/restconf/operations/GENERIC-RESOURCE-API:preload-network-topology-operation'
+ self.sdnc_preload_vnf_url = 'https://' + self.hosts['sdnc'] + \
':' + self.sdnc_preloading_port + '/restconf/operations/VNF-API:preload-vnf-topology-operation'
- self.sdnc_preload_gra_url = 'http://' + self.hosts['sdnc'] + \
+ self.sdnc_preload_gra_url = 'https://' + self.hosts['sdnc'] + \
':' + self.sdnc_preloading_port + '/restconf/operations/GENERIC-RESOURCE-API:preload-vf-module-topology-operation'
- self.sdnc_ar_cleanup_url = 'http://' + self.hosts['sdnc'] + ':' + self.sdnc_preloading_port + \
+ self.sdnc_ar_cleanup_url = 'https://' + self.hosts['sdnc'] + ':' + self.sdnc_preloading_port + \
'/restconf/config/GENERIC-RESOURCE-API:'
#############################################################################################
self.vpp_api_userpass = ('admin', 'admin')
self.vpp_ves_url= 'http://{0}:8183/restconf/config/vesagent:vesagent'
- def headbridge(self, openstack_stack_name, svc_instance_uuid):
+ #############################################################################################
+ # POLICY urls
+ self.policy_userpass = ('healthcheck', 'zb!XztG34')
+ self.policy_headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}
+ self.policy_api_url = 'https://{0}:6969/policy/api/v1/policytypes/onap.policies.controlloop.Operational/versions/1.0.0/policies'
+ self.policy_pap_get_url = 'https://{0}:6969/policy/pap/v1/pdps'
+ self.policy_pap_json = {'policies': [{'policy-id': 'operational.vcpe'}]}
+ self.policy_pap_post_url = self.policy_pap_get_url + '/policies'
+ self.policy_api_service_name = 'policy-api'
+ self.policy_pap_service_name = 'policy-pap'
+
+ #############################################################################################
+ # MARIADB-GALERA settings
+ self.mariadb_galera_endpoint_ip = self.get_k8s_service_endpoint_info('mariadb-galera','ip')
+ self.mariadb_galera_endpoint_port = self.get_k8s_service_endpoint_info('mariadb-galera','port')
+
+ #############################################################################################
+ # AAI urls
+ self.aai_region_query_url = 'https://' + self.oom_so_sdnc_aai_ip + ':' +\
+ self.aai_query_port +\
+ '/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/CloudOwner/' +\
+ self.cloud['--os-region-name']
+ self.aai_headers = {'Accept': 'application/json',
+ 'Content-Type': 'application/json',
+ 'X-FromAppId': 'postman', 'X-TransactionId': '9999'}
+
+ def heatbridge(self, openstack_stack_name, svc_instance_uuid):
"""
Add vserver information to AAI
"""
Check table DHCP_MAP in the SDNC DB. Find the newly instantiated BRG MAC address.
Note that there might be multiple BRGs, the most recently instantiated BRG always has the largest IP address.
"""
- cnx = mysql.connector.connect(user=self.sdnc_db_user, password=self.sdnc_db_pass, database=self.sdnc_db_name,
- host=self.hosts['sdnc'], port=self.sdnc_db_port)
+ if self.oom_mode:
+ db_host=self.mariadb_galera_endpoint_ip
+ else:
+ db_host=self.hosts['mariadb-galera']
+
+ cnx = mysql.connector.connect(user=self.sdnc_db_user,
+ password=self.sdnc_db_pass,
+ database=self.sdnc_db_name,
+ host=db_host,
+ port=self.sdnc_db_port)
cursor = cnx.cursor()
query = "SELECT * from DHCP_MAP"
cursor.execute(query)
mac_recent = None
host = -1
for mac, ip in cursor:
- self.logger.debug(mac + ':' + ip)
+ self.logger.debug(mac + ' - ' + ip)
this_host = int(ip.split('.')[-1])
if host < this_host:
host = this_host
cnx.close()
- assert mac_recent
+ try:
+ assert mac_recent
+ except AssertionError:
+ self.logger.error('Failed to obtain BRG MAC address from database')
+ sys.exit(1)
+
return mac_recent
+ def execute_cmds_mariadb(self, cmds):
+ self.execute_cmds_db(cmds, self.sdnc_db_user, self.sdnc_db_pass,
+ self.sdnc_db_name, self.mariadb_galera_endpoint_ip,
+ self.mariadb_galera_endpoint_port)
+
def execute_cmds_sdnc_db(self, cmds):
self.execute_cmds_db(cmds, self.sdnc_db_user, self.sdnc_db_pass, self.sdnc_db_name,
self.hosts['sdnc'], self.sdnc_db_port)
if filenamepath:
self.logger.error('Multiple files found for *{0}*.{1} in '
'directory {2}'.format(file_name_keyword, file_ext, search_dir))
- sys.exit()
+ sys.exit(1)
filenamepath = os.path.abspath(os.path.join(search_dir, file_name))
if filenamepath:
return filenamepath
else:
self.logger.error("Cannot find *{0}*{1} in directory {2}".format(file_name_keyword, file_ext, search_dir))
- sys.exit()
+ sys.exit(1)
@staticmethod
def network_name_to_subnet_name(network_name):
self.logger.error("Can't get subnet info from network name: " + network_name)
return False
+ def set_closed_loop_policy(self, policy_template_file):
+ # Gather policy services cluster ips
+ p_api_cluster_ip = self.get_k8s_service_cluster_ip(self.policy_api_service_name)
+ p_pap_cluster_ip = self.get_k8s_service_cluster_ip(self.policy_pap_service_name)
+
+ # Read policy json from file
+ with open(policy_template_file) as f:
+ try:
+ policy_json = json.load(f)
+ except ValueError:
+ self.logger.error(policy_template_file + " doesn't seem to contain valid JSON data")
+ sys.exit(1)
+
+ # Check policy already applied
+ policy_exists_req = requests.get(self.policy_pap_get_url.format(
+ p_pap_cluster_ip), auth=self.policy_userpass,
+ verify=False, headers=self.policy_headers)
+ if policy_exists_req.status_code != 200:
+ self.logger.error('Failure in checking CL policy existence. '
+ 'Policy-pap responded with HTTP code {0}'.format(
+ policy_exists_req.status_code))
+ sys.exit(1)
+
+ try:
+ policy_exists_json = policy_exists_req.json()
+ except ValueError as e:
+ self.logger.error('Policy-pap request failed: ' + e.message)
+ sys.exit(1)
+
+ try:
+ assert policy_exists_json['groups'][0]['pdpSubgroups'] \
+ [1]['policies'][0]['name'] != 'operational.vcpe'
+ except AssertionError:
+ self.logger.info('vCPE closed loop policy already exists, not applying')
+ return
+ except IndexError:
+ pass # policy doesn't exist
+
+ # Create policy
+ policy_create_req = requests.post(self.policy_api_url.format(
+ p_api_cluster_ip), auth=self.policy_userpass,
+ json=policy_json, verify=False,
+ headers=self.policy_headers)
+ # Get the policy id from policy-api response
+ if policy_create_req.status_code != 200:
+ self.logger.error('Failed creating policy. Policy-api responded'
+ ' with HTTP code {0}'.format(policy_create_req.status_code))
+ sys.exit(1)
+
+ try:
+ policy_version = json.loads(policy_create_req.text)['policy-version']
+ except (KeyError, ValueError):
+ self.logger.error('Policy API response not understood:')
+ self.logger.debug('\n' + str(policy_create_req.text))
+
+ # Inject the policy into Policy PAP
+ self.policy_pap_json['policies'].append({'policy-version': policy_version})
+ policy_insert_req = requests.post(self.policy_pap_post_url.format(
+ p_pap_cluster_ip), auth=self.policy_userpass,
+ json=self.policy_pap_json, verify=False,
+ headers=self.policy_headers)
+ if policy_insert_req.status_code != 200:
+ self.logger.error('Policy PAP request failed with HTTP code'
+ '{0}'.format(policy_insert_req.status_code))
+ sys.exit(1)
+ self.logger.info('Successully pushed closed loop Policy')
+
def is_node_in_aai(self, node_type, node_uuid):
key = None
search_node_type = None
key = 'vnf-id'
else:
logging.error('Invalid node_type: ' + node_type)
- sys.exit()
+ sys.exit(1)
url = 'https://{0}:{1}/aai/v11/search/nodes-query?search-node-type={2}&filter={3}:EQUALS:{4}'.format(
self.hosts['aai-inst1'], self.aai_query_port, search_node_type, key, node_uuid)
headers = {'Content-Type': 'application/json', 'Accept': 'application/json', 'X-FromAppID': 'vCPE-Robot', 'X-TransactionId': 'get_aai_subscr'}
- requests.packages.urllib3.disable_warnings()
r = requests.get(url, headers=headers, auth=self.aai_userpass, verify=False)
response = r.json()
self.logger.debug('aai query: ' + url)
break
if ret is None:
- ret = raw_input("Enter sdnc-sdnc-0 pod cluster node OAM IP address(10.0.0.0/16): ")
+ ret = raw_input("Enter " + self.sdnc_controller_pod + " pod cluster node OAM IP address(10.0.0.0/16): ")
return ret
def get_pod_node_public_ip(self, pod):
break
if ret is None:
- ret = raw_input("Enter sdnc-sdnc-0 pod cluster node public IP address(i.e. 10.12.0.0/16): ")
+ ret = raw_input("Enter " + self.sdnc_controller_pod + " pod cluster node public IP address(i.e. " + self.external_net_addr + "): ")
return ret
def get_vm_public_ip_by_nova(self, vm):
self.logger.error('Cannot find all desired IP addresses for %s.', keywords)
self.logger.error(json.dumps(ip_dict, indent=4, sort_keys=True))
self.logger.error('Temporarily continue.. remember to check back vcpecommon.py line: 396')
-# sys.exit()
+# sys.exit(1)
return ip_dict
def get_oom_onap_vm_ip(self, keywords):
vm_ip = {}
- onap_vm_list = set(['sdc', 'so', 'sdnc', 'aai-inst1', 'robot', self.dcae_ves_collector_name])
for vm in keywords:
- if vm in onap_vm_list:
+ if vm in self.host_names:
vm_ip[vm] = self.oom_so_sdnc_aai_ip
return vm_ip
+ def get_k8s_service_cluster_ip(self, service):
+ """
+ Returns cluster IP for a given service
+ :param service: name of the service
+ :return: cluster ip
+ """
+ config.load_kube_config()
+ api = client.CoreV1Api()
+ kslogger = logging.getLogger('kubernetes')
+ kslogger.setLevel(logging.INFO)
+ try:
+ resp = api.read_namespaced_service(service, self.onap_namespace)
+ except client.rest.ApiException as e:
+ self.logger.error('Error while making k8s API request: ' + e.body)
+ sys.exit(1)
+
+ return resp.spec.cluster_ip
+
+ def get_k8s_service_endpoint_info(self, service, subset):
+ """
+ Returns endpoint data for a given service and subset. If there
+ is more than one endpoint returns data for the first one from
+ the list that API returned.
+ :param service: name of the service
+ :param subset: subset name, one of "ip","port"
+ :return: endpoint ip
+ """
+ config.load_kube_config()
+ api = client.CoreV1Api()
+ kslogger = logging.getLogger('kubernetes')
+ kslogger.setLevel(logging.INFO)
+ try:
+ resp = api.read_namespaced_endpoints(service, self.onap_namespace)
+ except client.rest.ApiException as e:
+ self.logger.error('Error while making k8s API request: ' + e.body)
+ sys.exit(1)
+
+ if subset == "ip":
+ return resp.subsets[0].addresses[0].ip
+ elif subset == "port":
+ return resp.subsets[0].ports[0].port
+ else:
+ self.logger.error("Unsupported subset type")
+
def extract_vm_ip_as_dict(self, novalist_results, net_addr, net_addr_len):
vm_ip_dict = {}
for line in novalist_results.split('\n'):