From b718a43380376d2b19222c4203c97a95ca849ae8 Mon Sep 17 00:00:00 2001 From: Gerard Damm Date: Tue, 15 May 2018 14:53:18 -0500 Subject: May 15th update (identity, router gateway, options, summary) JIRA: AUTO-38 Automated configuration of an OpenStack instance for ONAP Updates: - using identity proxy now works - attaching a gateway to a router now works (at router creation) - added --debug and --delete options - added summary display at the end, with network IDs (for YAML files) Not yet working: - existence tests and deletions, waiting on OS-SDK bug fix (equality test in Resource.py) - assigning user to project using SDK identity proxy (no such method yet in SDK identity proxy) Signed-off-by: Gerard Damm Change-Id: I69c922c1e3a3ab94988d470637251598124b98ac --- .../auto_script_config_openstack_for_onap.py | 699 +++++++++++++-------- 1 file changed, 450 insertions(+), 249 deletions(-) diff --git a/setup/VIMs/OpenStack/auto_script_config_openstack_for_onap.py b/setup/VIMs/OpenStack/auto_script_config_openstack_for_onap.py index 88ba037..bab2c59 100644 --- a/setup/VIMs/OpenStack/auto_script_config_openstack_for_onap.py +++ b/setup/VIMs/OpenStack/auto_script_config_openstack_for_onap.py @@ -43,15 +43,15 @@ Auto project: https://wiki.opnfv.org/pages/viewpage.action?pageId=12389095 # 2) create an ONAP user within the ONAP project, so as not to use the "admin" user for ONAP # (associate user to group if applicable; credentials: name/pwd or name/APIkey, or token) # 3) create an ONAP security group, to allow ICMP traffic (for pings) and TCP port 22 (for SSH), rather than changing default security group(s) -# (optional, probably not needed: create new region) -# 4a) create a public network for ONAP VNFs, with ports, subnet, and CIDR block -# (or maybe not necessary? floating_net serves as public/external network and provides pool of floating IP@) -# 4b) create an OAM network for ONAP VNFs, with ports, subnet, and CIDR block -# (ONAP VNFs will be deployed in this OMA/private network, which will be connected by router to an external network) -# 5) create an OpenStack router, with an interface to the OAM/private network (and one to the public network?) -# and a reference to an external network (gateway) -# 6) create VM flavors as needed: m1.medium, etc. -# 7) download images, as needed for ONAP-deployed VNFs: e.g. Ubuntu 14.04, 16.04, ... +# (optional, probably not needed: create new region; default region RegionOne is OK) +# 4) create a public network for ONAP VNFs, with subnet and CIDR block +# (so components have access to the Internet, via router and gateway, on unnamed ports, dynamic IP@ allocation) +# 5) create a private and an OAM network for ONAP VNFs or other ONAP components, with their respective subnet and CIDR block +# (ONAP VNFs will be deployed in this private and/or OAM network(s), usually with named ports and static IP@ as per VNF configuration file) +# 6) create an OpenStack router, with interfaces to the public, private and OAM networks, +# and a reference to an external network (gateway) provided by the OpenStack instance installation +# 7) create VM flavors as needed: m1.medium, etc. +# 8) download VM images, as needed for ONAP-deployed VNFs: e.g. Ubuntu 14.04, 16.04, ... ###################################################################### @@ -81,34 +81,41 @@ Auto project: https://wiki.opnfv.org/pages/viewpage.action?pageId=12389095 ###################################################################### # script parameters -ONAP_USER_NAME = 'onap_user' -ONAP_USER_PASSWORD = 'auto_topsecret' -ONAP_USER_DESC = 'OpenStack User created for ONAP' +ONAP_USER_NAME = 'ONAP_user' +ONAP_USER_PASSWORD = 'auto_topsecret' +ONAP_USER_DESC = 'OpenStack User created for ONAP' -ONAP_TENANT_NAME = 'onap_tenant' # "project" is a more generic concept than "tenant"; a tenant is type of project -ONAP_TENANT_DESC = 'OpenStack Project/Tenant created for ONAP' +ONAP_TENANT_NAME = 'ONAP_tenant' # "project" is a more generic concept than "tenant"; a tenant is type of project; quotas are per project; +ONAP_TENANT_DESC = 'OpenStack Project/Tenant created for ONAP' -ONAP_SECU_GRP_NAME = 'ONAP security group' -ONAP_SECU_GRP_DESC = 'Security Group for ONAP' +ONAP_SECU_GRP_NAME = 'ONAP_security_group' +ONAP_SECU_GRP_DESC = 'Security Group created for ONAP' -ONAP_PUBLIC_NET_NAME = 'onap_public_net' -ONAP_PUBLIC_SUBNET_NAME = 'onap_public_subnet' -ONAP_PUBLIC_SUBNET_CIDR = '10.0.0.0/16' -ONAP_PUBLIC_NET_DESC = 'Public network created for ONAP' +ONAP_PUBLIC_NET_NAME = 'ONAP_public_net' +ONAP_PUBLIC_SUBNET_NAME = 'ONAP_public_subnet' +ONAP_PUBLIC_SUBNET_CIDR = '192.168.99.0/24' # some arbitrary CIDR, but typically in a private (IANA-reserved) address range +ONAP_PUBLIC_NET_DESC = 'Public network created for ONAP, for unnamed ports, dynamic IP@, access to the Internet (e.g., Nexus repo) via Gateway' -ONAP_OAM_NET_NAME = 'onap_oam_net' -ONAP_OAM_SUBNET_NAME = 'onap_oam_subnet' -ONAP_OAM_SUBNET_CIDR = '192.168.30.0/24' -ONAP_OAM_NET_DESC = 'OAM network created for ONAP' +ONAP_PRIVATE_NET_NAME = 'ONAP_private_net' +ONAP_PRIVATE_SUBNET_NAME = 'ONAP_private_subnet' +ONAP_PRIVATE_SUBNET_CIDR = '10.0.0.0/16' # should match ONAP installation; Private and OAM may be the same network +ONAP_PRIVATE_NET_DESC = 'Private network created for ONAP, for named ports, static IP@, inter-component communication' -ONAP_ROUTER_NAME = 'onap_router' -ONAP_ROUTER_DESC = 'Router created for ONAP' +ONAP_OAM_NET_NAME = 'ONAP_OAM_net' +ONAP_OAM_SUBNET_NAME = 'ONAP_OAM_subnet' +ONAP_OAM_SUBNET_CIDR = '10.99.0.0/16' # should match ONAP installation; Private and OAM may be the same network +ONAP_OAM_NET_DESC = 'OAM network created for ONAP, for named ports, static IP@, inter-component communication' -EXTERNAL_NETWORK_NAME = 'floating_net' # external network (gateway) name to be used in OpenStack instance +ONAP_ROUTER_NAME = 'ONAP_router' +ONAP_ROUTER_DESC = 'Router created for ONAP' + +EXTERNAL_NETWORK_NAME = 'floating_net' # OpenStack instance external network (gateway) name to be used as router's gateway + +ONAP_KEYPAIR_NAME = 'ONAP_keypair' # keypair that can be used to SSH into created servers (VNF VMs) # OpenStack cloud name and region name, which should be the same as in the clouds.yaml file used by this script -OPENSTACK_CLOUD_NAME = 'hpe16openstackFraser' -OPENSTACK_REGION_NAME = 'RegionOne' +OPENSTACK_CLOUD_NAME = 'hpe16openstackFraser' +OPENSTACK_REGION_NAME = 'RegionOne' # OpenStack domain is: Default @@ -119,126 +126,198 @@ DNS_SERVER_IP = '8.8.8.8' # - IPv4: 8.8.8.8 and 8.8.4.4 # - IPv6: 2001:4860:4860::8888 and 2001:4860:4860::8844 +###################################################################### +# global variables +DEBUG_VAR = False ###################################################################### # import statements import openstack import argparse +import sys, traceback +###################################################################### +def print_debug(*args): + if DEBUG_VAR: + for arg in args: + print ('***',arg) ###################################################################### def delete_all_ONAP(): """Delete all ONAP-specific OpenStack objects (normally not needed, but may be useful during tests).""" - print("\nOPNFV Auto, script to delete ONAP objects in an OpenStack instance") + print('\nOPNFV Auto, script to delete ONAP objects in an OpenStack instance') try: # connect to OpenStack instance using Connection object from OpenStack SDK - conn = openstack.connect(cloud=OPENSTACK_CLOUD_NAME, region_name=OPENSTACK_REGION_NAME) + print('Opening connection...') + conn = openstack.connect( + identity_api_version = 3, # must indicate Identity version (until fixed); can also be in clouds.yaml + cloud = OPENSTACK_CLOUD_NAME, + region_name = OPENSTACK_REGION_NAME) - # delete router; must delete router before networks. - onap_router = conn.network.find_router(ONAP_ROUTER_NAME) - print('DEBUG onap_router:\n',onap_router,'\n\n') + # delete router; must delete router before networks (and must delete VMs before routers) + print('Deleting ONAP router...') + onap_router = conn.network.find_router(ONAP_ROUTER_NAME) + print_debug('onap_router:',onap_router) if onap_router != None: - print('Deleting ONAP router...') conn.network.delete_router(onap_router.id) else: print('No ONAP router found...') + + # try: # try to circumvent !=None issue with OpenStack Resource.py; nope; + # onap_router = conn.network.find_router(ONAP_ROUTER_NAME) + # print_debug('onap_router:',onap_router) + # print_debug('onap_router.name:',onap_router.name) + # print_debug('onap_router.id:',onap_router.id) + # conn.network.delete_router(onap_router.id) + # conn.network.delete_router(onap_router) + # except Exception as e: + # print('issue Deleting ONAP router...') + # print('*** Exception:',type(e), e) + # exceptionType, exceptionValue, exceptionTraceback = sys.exc_info() + # print('*** traceback.print_tb():') + # traceback.print_tb(exceptionTraceback) + # print('*** traceback.print_exception():') + # traceback.print_exception(exceptionType, exceptionValue, exceptionTraceback) + + + # delete private network (which should also delete associated subnet and ports if any) + print('Deleting ONAP private network...') + private_network = conn.network.find_network(ONAP_PRIVATE_NET_NAME) + print_debug('private_network:',private_network) + if private_network != None: + conn.network.delete_network(private_network.id) + else: + print('No ONAP private network found...') + # delete OAM network (which should also delete associated subnet and ports if any) + print('Deleting ONAP OAM network...') oam_network = conn.network.find_network(ONAP_OAM_NET_NAME) - print('DEBUG oam_network:\n',oam_network,'\n\n') + print_debug('oam_network:',oam_network) if oam_network != None: - print('Deleting ONAP OAM network...') conn.network.delete_network(oam_network.id) else: print('No ONAP OAM network found...') # delete public network (which should also delete associated subnet and ports if any) + print('Deleting ONAP public network...') public_network = conn.network.find_network(ONAP_PUBLIC_NET_NAME) - print('DEBUG public_network:\n',public_network,'\n\n') + print_debug('public_network:',public_network) if public_network != None: - print('Deleting ONAP public network...') conn.network.delete_network(public_network.id) else: print('No ONAP public network found...') # delete security group + print('Deleting ONAP security group...') onap_security_group = conn.network.find_security_group(ONAP_SECU_GRP_NAME) - print('DEBUG onap_security_group:\n',onap_security_group,'\n\n') + print_debug('onap_security_group:',onap_security_group) if onap_security_group != None: - print('Deleting ONAP security group...') conn.network.delete_security_group(onap_security_group.id) else: print('No ONAP security group found...') - # # delete user - # onap_user = conn.identity.find_user(ONAP_USER_NAME) - # if onap_user != None: - # print('Deleting ONAP user...') - # conn.identity.delete_user(onap_user.id) - # else: - # print('No ONAP user found...') + # delete user + print('Deleting ONAP user...') + onap_user = conn.identity.find_user(ONAP_USER_NAME) + print_debug('onap_user:',onap_user) + if onap_user != None: + conn.identity.delete_user(onap_user.id) + else: + print('No ONAP user found...') + + # delete project/tenant + print('Deleting ONAP project...') + onap_project = conn.identity.find_project(ONAP_TENANT_NAME) + print_debug('onap_project:',onap_project) + if onap_project != None: + conn.identity.delete_project(onap_project.id) + else: + print('No ONAP project found...') + + # delete keypair + print('Deleting ONAP keypair...') + onap_keypair = conn.compute.find_keypair(ONAP_KEYPAIR_NAME) + print_debug('onap_keypair:',onap_keypair) + if onap_keypair != None: + conn.compute.delete_keypair(onap_keypair.id) + else: + print('No ONAP keypair found...') - # # delete project/tenant - # onap_project = conn.identity.find_project(ONAP_TENANT_NAME) - # if onap_project != None: - # print('Deleting ONAP project...') - # conn.identity.delete_project(onap_project.id) - # else: - # print('No ONAP project found...') except Exception as e: - print("Exception:",type(e), e) - print("[Script terminated]\n") + print('*** Exception:',type(e), e) + exceptionType, exceptionValue, exceptionTraceback = sys.exc_info() + print('*** traceback.print_tb():') + traceback.print_tb(exceptionTraceback) + print('*** traceback.print_exception():') + traceback.print_exception(exceptionType, exceptionValue, exceptionTraceback) + print('[Script terminated]\n') - print("OPNFV Auto, end of deletion script\n") + print('OPNFV Auto, end of deletion script\n') ###################################################################### def configure_all_ONAP(): """Configure all ONAP-specific OpenStack objects.""" - print("\nOPNFV Auto, script to configure an OpenStack instance for ONAP") + print('\nOPNFV Auto, script to configure an OpenStack instance for ONAP') try: # connect to OpenStack instance using Connection object from OpenStack SDK print('Opening connection...') - conn = openstack.connect(cloud=OPENSTACK_CLOUD_NAME, region_name=OPENSTACK_REGION_NAME) - + conn = openstack.connect( + identity_api_version = 3, # must indicate Identity version (until fixed); can also be in clouds.yaml + cloud = OPENSTACK_CLOUD_NAME, + region_name = OPENSTACK_REGION_NAME) + ################################################################### # TESTS: IGNORE/DELETE (BEGIN) # gdserver_ID = '8bc274a2-8c0d-4795-9b4d-faa0a21e1d88' # gdserver = conn.compute.get_server(gdserver_ID) # print('\ngdserver.name=',gdserver.name) # print('gdserver.status=',gdserver.status) - # # print("\nList Users:") - # # i=1 - # # for user in conn.identity.users(): - # # print('User',str(i),'\n',user,'\n') - # # i+=1 + # print("\nList Users:") + # i=1 + # for user in conn.identity.users(): + # print('User',str(i),user.name,'\n',user,'\n') + # i+=1 - # # print("\nList Projects:") - # # i=1 - # # for project in conn.identity.projects(): - # # print('Project',str(i),'\n',project,'\n') - # # i+=1 + # print("\nList Projects:") + # i=1 + # for project in conn.identity.projects(): + # print('Project',str(i),project.name,'\n',project,'\n') + # i+=1 + + # print("\nList Roles:") + # i=1 + # for role in conn.identity.roles(): + # print('Role',str(i),role.name,'\n',role,'\n') + # i+=1 # print("\nList Networks:") # i=1 # for network in conn.network.networks(): - # print('Network',str(i),'\n',network,'\n') + # print('Network',str(i),network.name,'\n',network,'\n') + # i+=1 + + # print("\nList Routers:") + # i=1 + # for router in conn.network.routers(): + # print('Router',str(i),router.name,'\n',router,'\n') # i+=1 # print("\nList Flavors:") # i=1 # for flvr in conn.compute.flavors(): - # print('Flavor',str(i),'\n',flvr,'\n') + # print('Flavor',str(i),flvr.name,'\n',flvr,'\n') # i+=1 # print("\nList Images:") # i=1 # for img in conn.compute.images(): - # print('Image',str(i),'\n',img,'\n') + # print('Image',str(i),img.name,'\n',img,'\n') # i+=1 # router = conn.network.find_router('gd_test_router') @@ -246,61 +325,67 @@ def configure_all_ONAP(): # router = conn.network.find_router('e4e59f63-8063-4774-a97a-c110c6969e4a') # print('gd router\n',router,'\n\n') # TESTS: IGNORE/DELETE (END) + ################################################################### - - # TODO: find out why conn.identity does not exist @@@ - # onap_project = conn.identity.find_project(ONAP_TENANT_NAME) - # if onap_project != None: - # print('ONAP project/tenant already exists') - # else: - # print('Creating ONAP project/tenant...') - # onap_project = conn.identity.create_project( - # name = ONAP_TENANT_NAME, - # description = ONAP_TENANT_DESC, - # is_enabled = True) - # # domain: leave default - # # project quotas (max #vCPUs, #instances, etc.): as conn.network.<*quota*>, using project id for quota id - # # https://docs.openstack.org/openstacksdk/latest/user/proxies/network.html#quota-operations - # # https://docs.openstack.org/openstacksdk/latest/user/resources/network/v2/quota.html#openstack.network.v2.quota.Quota - # # conn.network.update_quota(project_id = onap_project.id) - # # SDK for quotas supports floating_ips, networks, ports, etc. but not vCPUs or instances - # print('DEBUG onap_project:\n',onap_project,'\n\n') - - # onap_user= conn.identity.find_user(ONAP_USER_NAME) - # if onap_user != None: - # print('ONAP user already exists') - # else: - # print('Creating ONAP user...') - # onap_user = conn.identity.create_user( - # name = ONAP_USER_NAME, - # description = ONAP_USER_DESC, - # default_project_id = onap_project.id, - # password = ONAP_USER_PASSWORD, - # is_enabled = True) - # # domain: leave default - # # default_project_id: primary project - # print('DEBUG onap_user:\n',onap_user,'\n\n') - - + print('Creating ONAP project/tenant...') + onap_project = conn.identity.find_project(ONAP_TENANT_NAME) + if onap_project != None: + print('ONAP project/tenant already exists') + else: + onap_project = conn.identity.create_project( + name = ONAP_TENANT_NAME, + description = ONAP_TENANT_DESC, + is_enabled = True) + # domain: leave default + # project quotas (max #vCPUs, #instances, etc.): as conn.network.<*quota*>, using project id for quota id + # https://docs.openstack.org/openstacksdk/latest/user/proxies/network.html#quota-operations + # https://docs.openstack.org/openstacksdk/latest/user/resources/network/v2/quota.html#openstack.network.v2.quota.Quota + # conn.network.update_quota(project_id = onap_project.id) + # SDK for quotas supports floating_ips, networks, ports, etc. but not vCPUs or instances + print_debug('onap_project:',onap_project) + + + print('Creating ONAP user...') + onap_user = conn.identity.find_user(ONAP_USER_NAME) + if onap_user != None: + print('ONAP user already exists') + else: + onap_user = conn.identity.create_user( + name = ONAP_USER_NAME, + description = ONAP_USER_DESC, + default_project_id = onap_project.id, + password = ONAP_USER_PASSWORD, + is_enabled = True) + # domain: leave default + # default_project_id: primary project + print_debug('onap_user:',onap_user) + + # TODO@@@ assign Member role to ONAP user in ONAP project + # membership_role = conn.identity.find_role('Member') + # onap_project.assign_role_to_user(conn, onap_user, membership_role) # no project membership method yet in connection proxy + + # TODO@@@ maybe logout and log back in as ONAP user # make sure security group allows ICMP (for ping) and SSH (TCP port 22) traffic; also IPv4/v6 traffic ingress and egress # create new onap_security_group (or maybe just "default" security group ? tests returned multiple "default" security groups) # security group examples: check http://git.openstack.org/cgit/openstack/openstacksdk/tree/examples/network/security_group_rules.py # if rule already exists, OpenStack returns an error, so just try (no harm); try each separately + # (SecurityGroup is a Resource) + print('Creating ONAP security group...') onap_security_group = conn.network.find_security_group(ONAP_SECU_GRP_NAME) - if onap_security_group == None: + if onap_security_group != None: + print('ONAP security group already exists') + else: onap_security_group = conn.network.create_security_group( - # project_id = onap_project.id, + #project_id = onap_project.id, description = ONAP_SECU_GRP_DESC, name = ONAP_SECU_GRP_NAME) - else: - print('ONAP security group already exists') - print('DEBUG onap_security_group:\n',onap_security_group,'\n\n') + print_debug('onap_security_group:',onap_security_group) try: description_text = 'enable ICMP ingress IPv4' - print('Creating rule:',description_text,'...') + print(' Creating rule:',description_text,'...') conn.network.create_security_group_rule( security_group_id = onap_security_group.id, description = description_text, @@ -315,7 +400,7 @@ def configure_all_ONAP(): try: description_text = 'enable ICMP egress IPv4' - print('Creating rule:',description_text,'...') + print(' Creating rule:',description_text,'...') conn.network.create_security_group_rule( security_group_id = onap_security_group.id, description = description_text, @@ -330,7 +415,7 @@ def configure_all_ONAP(): try: description_text = 'enable SSH (TCP port 22) ingress IPv4' - print('Creating rule:',description_text,'...') + print(' Creating rule:',description_text,'...') conn.network.create_security_group_rule( security_group_id = onap_security_group.id, description = description_text, @@ -345,7 +430,7 @@ def configure_all_ONAP(): try: description_text = 'enable SSH (TCP port 22) egress IPv4' - print('Creating rule:',description_text,'...') + print(' Creating rule:',description_text,'...') conn.network.create_security_group_rule( security_group_id = onap_security_group.id, description = description_text, @@ -360,7 +445,7 @@ def configure_all_ONAP(): try: description_text = 'enable IP traffic ingress IPv4' - print('Creating rule:',description_text,'...') + print(' Creating rule:',description_text,'...') conn.network.create_security_group_rule( security_group_id = onap_security_group.id, description = description_text, @@ -375,7 +460,7 @@ def configure_all_ONAP(): try: description_text = 'enable IP traffic ingress IPv6' - print('Creating rule:',description_text,'...') + print(' Creating rule:',description_text,'...') conn.network.create_security_group_rule( security_group_id = onap_security_group.id, description = description_text, @@ -391,7 +476,7 @@ def configure_all_ONAP(): # IPv4 IP egress rule should already exist by default # try: # description_text = 'enable IP traffic egress IPv4' - # print('Creating rule:',description_text,'...') + # print(' Creating rule:',description_text,'...') # conn.network.create_security_group_rule( # security_group_id = onap_security_group.id, # description = description_text, @@ -407,7 +492,7 @@ def configure_all_ONAP(): # IPv6 IP egress rule should already exist by default # try: # description_text = 'enable IP traffic egress IPv6' - # print('Creating rule:',description_text,'...') + # print(' Creating rule:',description_text,'...') # conn.network.create_security_group_rule( # security_group_id = onap_security_group.id, # description = description_text, @@ -422,11 +507,11 @@ def configure_all_ONAP(): # public network + print('Creating ONAP public network...') public_network = conn.network.find_network(ONAP_PUBLIC_NET_NAME) if public_network != None: print('ONAP public network already exists') else: - print('Creating ONAP public network...') public_network = conn.network.create_network( name = ONAP_PUBLIC_NET_NAME, description = ONAP_PUBLIC_NET_DESC, @@ -434,9 +519,9 @@ def configure_all_ONAP(): is_admin_state_up = True, is_shared = True) # subnet_ids = []: not needed, subnet refers to network_id - print('DEBUG public_network:\n',public_network,'\n\n') + print_debug('public_network: before subnet',public_network) - print('Creating subnetwork for ONAP public network...') + print(' Creating subnetwork for ONAP public network...') public_subnet = conn.network.create_subnet( name = ONAP_PUBLIC_SUBNET_NAME, #project_id = onap_project.id, @@ -445,25 +530,52 @@ def configure_all_ONAP(): ip_version = 4, is_dhcp_enabled = True, dns_nameservers = [DNS_SERVER_IP]) # list of DNS IP@ - print('DEBUG public_network:\n',public_network,'\n\n') - print('DEBUG public_subnet:\n',public_subnet,'\n\n') + print_debug('public_network: after subnet',public_network) + print_debug('public_subnet:',public_subnet) + + + # private network + print('Creating ONAP private network...') + private_network = conn.network.find_network(ONAP_PRIVATE_NET_NAME) + if private_network != None: + print('ONAP private network already exists') + else: + private_network = conn.network.create_network( + name = ONAP_PRIVATE_NET_NAME, + description = ONAP_PRIVATE_NET_DESC, + #project_id = onap_project.id, + is_admin_state_up = True, + is_shared = True) + print_debug('private_network: before subnet',private_network) + + print(' Creating subnetwork for ONAP private network...') + private_subnet = conn.network.create_subnet( + name = ONAP_PRIVATE_SUBNET_NAME, + #project_id = onap_project.id, + network_id = private_network.id, + cidr = ONAP_PRIVATE_SUBNET_CIDR, + ip_version = 4, + is_dhcp_enabled = True, + dns_nameservers = [DNS_SERVER_IP]) # list of DNS IP@; maybe not needed for private network + print_debug('private_network: after subnet',private_network) + print_debug('private_subnet:',private_subnet) # OAM network + print('Creating ONAP OAM network...') oam_network = conn.network.find_network(ONAP_OAM_NET_NAME) if oam_network != None: print('ONAP OAM network already exists') else: - print('Creating ONAP OAM network...') oam_network = conn.network.create_network( name = ONAP_OAM_NET_NAME, description = ONAP_OAM_NET_DESC, #project_id = onap_project.id, is_admin_state_up = True, is_shared = True) - print('DEBUG oam_network:\n',oam_network,'\n\n') + print_debug('oam_network: before subnet',oam_network) - print('Creating subnetwork for ONAP OAM network...') + print(' Creating subnetwork for ONAP OAM network...') oam_subnet = conn.network.create_subnet( name = ONAP_OAM_SUBNET_NAME, #project_id = onap_project.id, @@ -472,34 +584,56 @@ def configure_all_ONAP(): ip_version = 4, is_dhcp_enabled = True, dns_nameservers = [DNS_SERVER_IP]) # list of DNS IP@; maybe not needed for OAM network - print('DEBUG oam_network:\n',oam_network,'\n\n') - print('DEBUG oam_subnet:\n',oam_subnet,'\n\n') + print_debug('oam_network: after subnet',oam_network) + print_debug('oam_subnet:',oam_subnet) # router + print('Creating ONAP router...') onap_router = conn.network.find_router(ONAP_ROUTER_NAME) if onap_router != None: print('ONAP router already exists') else: - print('Creating ONAP router...') + + # build dictionary for external network (gateway) + external_network = conn.network.find_network(EXTERNAL_NETWORK_NAME) + print_debug('external_network:',external_network) + external_subnet_ID_list = external_network.subnet_ids + print_debug('external_subnet_ID_list:',external_subnet_ID_list) + # build external_fixed_ips: list of dictionaries, each with 'subnet_id' key (and may have 'ip_address' key as well) + onap_gateway_external_subnets = [] + for ext_subn_id in external_subnet_ID_list: # there should be only one subnet ID in the list, but go through each item, just in case + onap_gateway_external_subnets.append({'subnet_id':ext_subn_id}) + print_debug('onap_gateway_external_subnets:',onap_gateway_external_subnets) + network_dict_body = { + 'network_id': external_network.id, + 'enable_snat': True, # True should be the default, so there should be no need to set it + 'external_fixed_ips': onap_gateway_external_subnets + } + print_debug('network_dict_body:',network_dict_body) + onap_router = conn.network.create_router( name = ONAP_ROUTER_NAME, description = ONAP_ROUTER_DESC, #project_id = onap_project.id, + external_gateway_info = network_dict_body, # linking GW to router creation time (normally, could also use add_gateway_to_router) is_admin_state_up = True) - print('DEBUG onap_router:\n',onap_router,'\n\n') + print_debug('onap_router: after creation',onap_router) - # add interfaces to ONAP networks: Public and OAM + # add interfaces to ONAP networks: Public, Private, and OAM # syntax: add_interface_to_router(router, subnet_id=None, port_id=None) - print('Adding interfaces to ONAP router for ONAP public and OAM networks...') + print('Adding interface to ONAP router for ONAP public network...') conn.network.add_interface_to_router(onap_router, subnet_id = public_subnet.id) + print('Adding interface to ONAP router for ONAP private network...') + conn.network.add_interface_to_router(onap_router, subnet_id = private_subnet.id) + print('Adding interface to ONAP router for ONAP OAM network...') conn.network.add_interface_to_router(onap_router, subnet_id = oam_subnet.id) - print('DEBUG onap_router:\n',onap_router,'\n\n') + print_debug('onap_router: after adding interfaces',onap_router) - # not public network, but external network like floating_net - # point to ONAP Public Network as external network (i.e. Gateway); network_id is passed in a body dictionary + # point to OpenStack external network (i.e. Gateway for router); network_id is passed in a body dictionary + # (external network such as floating_net) # syntax: add_gateway_to_router(router, **body) - print('Adding external network (gateway) to ONAP router...') + #print('Adding external network (gateway) to ONAP router...') # nope # network_dict_body = {'network_id': public_network.id} @@ -508,98 +642,119 @@ def configure_all_ONAP(): # 'external_fixed_ips': [{'subnet_id' : public_subnet.id}], # 'network_id': public_network.id # } - external_network = conn.network.find_network(EXTERNAL_NETWORK_NAME) - print('DEBUG external_network:\n',external_network,'\n\n') - #network_dict_body = {'gateway' : {'network_id' : external_network.id}} - #conn.network.add_gateway_to_router(onap_router, body=network_dict_body) - conn.network.add_gateway_to_router(onap_router, network_id=external_network.id) + # external_network = conn.network.find_network(EXTERNAL_NETWORK_NAME) + # print_debug('external_network:',external_network) + # external_subnet_ID_list = external_network.subnet_ids + # print_debug('external_subnet_ID_list:',external_subnet_ID_list) - # also create 5 flavors, from tiny to xlarge (hard-coded, no need for parameters) - print('Creating flavors...') - tiny_flavor = conn.compute.find_flavor("m1.tiny") - if tiny_flavor != None: - print('m1.tiny Flavor already exists') - else: - print('Creating m1.tiny Flavor...') - tiny_flavor = conn.compute.create_flavor( - name = 'm1.tiny', - vcpus = 1, - disk = 1, - ram = 512, - ephemeral = 0, - #swap = 0, - #rxtx_factor = 1.0, - is_public = True) - print('DEBUG tiny_flavor:\n',tiny_flavor,'\n\n') - - small_flavor = conn.compute.find_flavor("m1.small") - if small_flavor != None: - print('m1.small Flavor already exists') - else: - print('Creating m1.small Flavor...') - small_flavor = conn.compute.create_flavor( - name = 'm1.small', - vcpus = 1, - disk = 20, - ram = 2048, - ephemeral = 0, - #swap = 0, - #rxtx_factor = 1.0, - is_public = True) - print('DEBUG small_flavor:\n',small_flavor,'\n\n') - - medium_flavor = conn.compute.find_flavor("m1.medium") - if medium_flavor != None: - print('m1.medium Flavor already exists') - else: - print('Creating m1.medium Flavor...') - medium_flavor = conn.compute.create_flavor( - name = 'm1.medium', - vcpus = 2, - disk = 40, - ram = 4096, - ephemeral = 0, - #swap = 0, - #rxtx_factor = 1.0, - is_public = True) - print('DEBUG medium_flavor:\n',medium_flavor,'\n\n') - - large_flavor = conn.compute.find_flavor("m1.large") - if large_flavor != None: - print('m1.large Flavor already exists') - else: - print('Creating m1.large Flavor...') - large_flavor = conn.compute.create_flavor( - name = 'm1.large', - vcpus = 4, - disk = 80, - ram = 8192, - ephemeral = 0, - #swap = 0, - #rxtx_factor = 1.0, - is_public = True) - print('DEBUG large_flavor:\n',large_flavor,'\n\n') - - xlarge_flavor = conn.compute.find_flavor("m1.xlarge") - if xlarge_flavor != None: - print('m1.xlarge Flavor already exists') - else: - print('Creating m1.xlarge Flavor...') - xlarge_flavor = conn.compute.create_flavor( - name = 'm1.xlarge', - vcpus = 8, - disk = 160, - ram = 16384, - ephemeral = 0, - #swap = 0, - #rxtx_factor = 1.0, - is_public = True) - print('DEBUG xlarge_flavor:\n',xlarge_flavor,'\n\n') + # # build external_fixed_ips: list of dictionaries, each with 'subnet_id' key (and may have 'ip_address' key as well) + # onap_gateway_external_subnets = [] + # for ext_subn_id in external_subnet_ID_list: # there should be only one subnet ID in the list, but go through each item, just in case + # onap_gateway_external_subnets.append({'subnet_id':ext_subn_id}) + + # #network_dict_body = {'gateway' : {'network_id' : external_network.id}} + # #network_dict_body = {'network_id' : external_network.id} + # #conn.network.add_gateway_to_router(onap_router, body=network_dict_body) + # #conn.network.add_gateway_to_router(onap_router, network_id=external_network.id) + # #conn.network.add_gateway_to_router(onap_router, **network_dict_body) + + # network_dict_body = { + # 'network_id': external_network.id, + # 'enable_snat': True, # True should be the default, so there should be no need to set it + # 'external_fixed_ips': onap_gateway_external_subnets + # } + # #conn.network.add_gateway_to_router(onap_router, **network_dict_body) + # print_debug('onap_router: after add_gateway_to_router',onap_router) - # also create 3 images, Ubuntu 16.04, 14.04, CirrOS + + # # also create 5 flavors, from tiny to xlarge (hard-coded, no need for parameters) + # # (Flavor is a Resource) + # print('Creating flavors...') + # print('Creating m1.tiny Flavor...') + # tiny_flavor = conn.compute.find_flavor("m1.tiny") + # if tiny_flavor != None: + # print('m1.tiny Flavor already exists') + # else: + # tiny_flavor = conn.compute.create_flavor( + # name = 'm1.tiny', + # vcpus = 1, + # disk = 1, + # ram = 512, + # ephemeral = 0, + # #swap = 0, + # #rxtx_factor = 1.0, + # is_public = True) + # print_debug('tiny_flavor: ',tiny_flavor) + + # print('Creating m1.small Flavor...') + # small_flavor = conn.compute.find_flavor("m1.small") + # if small_flavor != None: + # print('m1.small Flavor already exists') + # else: + # small_flavor = conn.compute.create_flavor( + # name = 'm1.small', + # vcpus = 1, + # disk = 20, + # ram = 2048, + # ephemeral = 0, + # #swap = 0, + # #rxtx_factor = 1.0, + # is_public = True) + # print_debug('small_flavor: ',small_flavor) + + # print('Creating m1.medium Flavor...') + # medium_flavor = conn.compute.find_flavor("m1.medium") + # if medium_flavor != None: + # print('m1.medium Flavor already exists') + # else: + # medium_flavor = conn.compute.create_flavor( + # name = 'm1.medium', + # vcpus = 2, + # disk = 40, + # ram = 4096, + # ephemeral = 0, + # #swap = 0, + # #rxtx_factor = 1.0, + # is_public = True) + # print_debug('medium_flavor: ',medium_flavor) + + # print('Creating m1.large Flavor...') + # large_flavor = conn.compute.find_flavor("m1.large") + # if large_flavor != None: + # print('m1.large Flavor already exists') + # else: + # large_flavor = conn.compute.create_flavor( + # name = 'm1.large', + # vcpus = 4, + # disk = 80, + # ram = 8192, + # ephemeral = 0, + # #swap = 0, + # #rxtx_factor = 1.0, + # is_public = True) + # print_debug('large_flavor: ',large_flavor) + + # print('Creating m1.xlarge Flavor...') + # xlarge_flavor = conn.compute.find_flavor("m1.xlarge") + # if xlarge_flavor != None: + # print('m1.xlarge Flavor already exists') + # else: + # xlarge_flavor = conn.compute.create_flavor( + # name = 'm1.xlarge', + # vcpus = 8, + # disk = 160, + # ram = 16384, + # ephemeral = 0, + # #swap = 0, + # #rxtx_factor = 1.0, + # is_public = True) + # print_debug('xlarge_flavor: ',xlarge_flavor) + + + # create images: Ubuntu 16.04, 14.04, CirrOS, ... # 64-bit QCOW2 image for cirros-0.4.0-x86_64-disk.img # description: CirrOS minimal Linux distribution # http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-x86_64-disk.img @@ -615,44 +770,90 @@ def configure_all_ONAP(): # http://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img # user: ubuntu + # do not use compute proxy for images; there is an image proxy (v1, and v2); use shade layer, directly with Connection object; + # conn.get_image() returns a Python Munch object (subclass of Dictionary) + # URL download not supported yet; download image separately, place it in the directory + # https://docs.openstack.org/openstacksdk/latest/user/connection.html#openstack.connection.Connection.create_image - # IMAGE_NAME = 'cirros-0.4.0-x86_64-disk.img' - # cirros040 = conn.compute.find_image(IMAGE_NAME) - # if cirros040 != None: - # print(IMAGE_NAME,'Image already exists') - # else: - # print('Creating',IMAGE_NAME,'Image ...') - # # no conn.compute.create_image() method yet in OpenStack SDK... unless doc is wrong ? - # cirros040 = conn.compute.create_image( - # name = IMAGE_NAME) - # # no support for URL download ? maybe with Image.metadata, or with ImageDetail class ? - # print('DEBUG cirros040:\n',cirros040,'\n\n') + IMAGE_NAME = 'CirrOS_0.4.0_minimal_Linux_distribution' + print('Creating image:',IMAGE_NAME,'...') + if conn.get_image(IMAGE_NAME) != None: + print(IMAGE_NAME,'image already exists') + else: + conn.create_image(IMAGE_NAME, filename='cirros-0.4.0-x86_64-disk.img') + IMAGE_NAME = 'Ubuntu_Server_16.04_LTS_Xenial_Xerus' + print('Creating image:',IMAGE_NAME,'...') + if conn.get_image(IMAGE_NAME) != None: + print(IMAGE_NAME,'image already exists') + else: + conn.create_image(IMAGE_NAME, filename='xenial-server-cloudimg-amd64-disk1.img') + + IMAGE_NAME = 'Ubuntu_Server_14.04_LTS_Trusty_Tahr' + print('Creating image:',IMAGE_NAME,'...') + if conn.get_image(IMAGE_NAME) != None: + print(IMAGE_NAME,'image already exists') + else: + conn.create_image(IMAGE_NAME, filename='trusty-server-cloudimg-amd64-disk1.img') + # create a keypair, if needed e.g. for VNF VMs; maybe to SSH for testing + # (Keypair is a Resource) + print('Creating ONAP keypair...') + onap_keypair = conn.compute.find_keypair(ONAP_KEYPAIR_NAME) + if onap_keypair != None: + print('ONAP keypair already exists') + else: + onap_keypair = conn.compute.create_keypair(name=ONAP_KEYPAIR_NAME) + print(' ONAP keypair fingerprint:') + print(onap_keypair.fingerprint) + print(' ONAP keypair public key:') + print(onap_keypair.public_key) + print(' \nONAP keypair private key: (save it in a file now: it cannot be retrieved later)') + print(onap_keypair.private_key) + print_debug('onap_keypair:',onap_keypair) + + print('\nSUMMARY:') + print('ONAP public network ID:',public_network.id) + print('ONAP private network ID:',private_network.id) + print('ONAP private network subnet ID:',private_subnet.id) + print('ONAP private network subnet CIDR:',private_subnet.cidr) + print('\n') except Exception as e: - print("Exception:",type(e), e) - print("[Script terminated]\n") + print('*** Exception:',type(e), e) + exceptionType, exceptionValue, exceptionTraceback = sys.exc_info() + print('*** traceback.print_tb():') + traceback.print_tb(exceptionTraceback) + print('*** traceback.print_exception():') + traceback.print_exception(exceptionType, exceptionValue, exceptionTraceback) + print('[Script terminated]\n') - print("OPNFV Auto, end of configuration script\n") + print('OPNFV Auto, end of configuration script\n') ###################################################################### def main(): - # configure argument parser: one optional argument - # if no "-d" or "--delete" option, then configure OpenStack for ONAP - # with "-d" or "--delete" option, then delete ONAP configuration in OpenStack + # configure argument parser: 2 optional arguments + # "-del" or "--delete" option to delete ONAP configuration in OpenStack + # (if no "-del" or "--delete", then configure OpenStack for ONAP + # "-deb" or "--debug" option to display debug information parser = argparse.ArgumentParser() - parser.add_argument("-d", "--delete", - help = "delete ONAP configuration", - action = "store_true") - - # parse arguments and use corresponding script + parser.add_argument('-deb', '--debug', + help = 'display debug information during execution', + action = 'store_true') + parser.add_argument('-del', '--delete', + help = 'delete ONAP configuration', + action = 'store_true') + + # parse arguments, modify global variable if need be, and use corresponding script args = parser.parse_args() + if args.debug: + global DEBUG_VAR + DEBUG_VAR = True if args.delete: delete_all_ONAP() else: -- cgit 1.2.3-korg