From 666d3a9009dcdb770ee0f4de736f7d10d33db29d Mon Sep 17 00:00:00 2001 From: Michal Zegan Date: Thu, 22 Aug 2019 15:02:06 +0200 Subject: Add the .gitignore for cicdansible Adds the .gitignore file for the ansible playbook. Change-Id: If6e52f55e045ccccd164992108d1977c2a46a413 Issue-ID: OOM-2042 Signed-off-by: Michal Zegan --- tools/cicdansible/.gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tools/cicdansible/.gitignore (limited to 'tools') diff --git a/tools/cicdansible/.gitignore b/tools/cicdansible/.gitignore new file mode 100644 index 00000000..bb3e4abb --- /dev/null +++ b/tools/cicdansible/.gitignore @@ -0,0 +1,2 @@ +*.retry +resources/ -- cgit 1.2.3-korg From 07479cbc38ef4bf15ea0c4854c8af08e1201a53d Mon Sep 17 00:00:00 2001 From: Michal Zegan Date: Thu, 22 Aug 2019 14:43:11 +0200 Subject: Add heat template to deploy onap infrastructure This change adds a heat template that deploys empty onap infrastructure on open stack. Infrastructure consists of an installer instance + infra instance + specified number of kubernetes nodes. All instances are empty after creation, and live in the internal network with cidr 10.1.0.0/24. They are isolated by security groups in order not to have external network access except possibly the intranet, but it is possible to enable internet access if required. Change-Id: I70024e1e2344ed75f443f03b2239b460a71d0151 Issue-ID: OOM-2042 Signed-off-by: Michal Zegan --- tools/cicdansible/heat/config.yaml | 10 ++ tools/cicdansible/heat/installer.env | 1 + tools/cicdansible/heat/installer.yaml | 283 ++++++++++++++++++++++++++++++++++ tools/cicdansible/heat/instance.yaml | 58 +++++++ tools/cicdansible/heat/node.yaml | 59 +++++++ 5 files changed, 411 insertions(+) create mode 100644 tools/cicdansible/heat/config.yaml create mode 100644 tools/cicdansible/heat/installer.env create mode 100644 tools/cicdansible/heat/installer.yaml create mode 100644 tools/cicdansible/heat/instance.yaml create mode 100644 tools/cicdansible/heat/node.yaml (limited to 'tools') diff --git a/tools/cicdansible/heat/config.yaml b/tools/cicdansible/heat/config.yaml new file mode 100644 index 00000000..e1f0309f --- /dev/null +++ b/tools/cicdansible/heat/config.yaml @@ -0,0 +1,10 @@ +#cloud-config +#Enable root login. +disable_root: false +#Output everything to /dev/console... +output: { all: "/dev/console" } +#Initialization. +runcmd: + - | + set -efxu -o pipefail + %{NOTIFY_COMMAND} --data-binary '{"status": "SUCCESS", "reason": "instance started successfully"}' diff --git a/tools/cicdansible/heat/installer.env b/tools/cicdansible/heat/installer.env new file mode 100644 index 00000000..9765ce30 --- /dev/null +++ b/tools/cicdansible/heat/installer.env @@ -0,0 +1 @@ +#Environment file diff --git a/tools/cicdansible/heat/installer.yaml b/tools/cicdansible/heat/installer.yaml new file mode 100644 index 00000000..8fff3a74 --- /dev/null +++ b/tools/cicdansible/heat/installer.yaml @@ -0,0 +1,283 @@ +#This is the environment heat template, compatible with openstack ocata. +heat_template_version: 2017-02-24 +description: "Heat template for deploying onap env" +parameters: + auth_key: + label: "Auth public key" + description: "The public key used to authenticate to instances" + type: string + node_flavor_name: + label: "name of node flavor" + description: "The name of the flavor used to create kubernetes nodes" + type: string + constraints: + - custom_constraint: nova.flavor + description: "need to specify a valid flavor" + infra_flavor_name: + label: "name of infra flavor" + description: "flavor used to create infra instance" + type: string + constraints: + - custom_constraint: nova.flavor + description: "need to specify a valid flavor" + installer_flavor_name: + label: "name of installer flavor" + description: "flavor used to create installer instance" + type: string + constraints: + - custom_constraint: nova.flavor + description: "need to specify a valid flavor" + image_name: + label: "image name" + description: "name of the image from which to create all instances, should be rhel 7.6 or centos image" + type: string + constraints: + - custom_constraint: glance.image + description: "must specify a valid image name" + subnet_cidr: + label: "private subnet cidr" + description: "Cidr of a private subnet instances will be connected to" + type: string + constraints: + - custom_constraint: net_cidr + subnet_range_start: + label: "subnet dhcp allocation range start" + description: "Start of range of dhcp allocatable ips on private subnet" + type: string + constraints: + - custom_constraint: ip_addr + subnet_range_end: + label: "end of subnet dhcp allocation range" + description: "End of private subnet's dhcp allocation range" + type: string + constraints: + - custom_constraint: ip_addr + router_addr: + label: "ip address of router" + description: "IP address of the router allowing access to other networks incl. company network" + type: string + constraints: + - custom_constraint: ip_addr + public_network_name: + label: "name of the public network" + description: "Name of the public, internet facing network, also allowing access to company internal hosts" + type: string + constraints: + - custom_constraint: neutron.network + description: "Must specify a valid network name or id" + external_subnet_cidr: + label: "external subnet cidr" + description: "The CIDR of the external subnet, that should be accessible from instances, even when internet access is cut. Putting 0.0.0.0/0 here means access to internet." + type: string + constraints: + - custom_constraint: net_cidr + installer_ip: + label: "floating ip of the installer" + description: "a pre-allocated floating ip that will be associated with the installer instance" + type: string + infra_ip: + label: "floating ip of the infra" + description: "a pre-allocated floating ip that will be associated with the infrastructure instance" + type: string + node_ip: + label: "floating ip of the first node" + description: "a pre-allocated floating ip that will be associated with the first kubernetes node and allow accessing onap" + type: string + num_nodes: + label: "num nodes" + description: "the number of kubernetes nodes to create, min 1" + type: number + constraints: + - range: { min: 1 } + description: "must be a positive number" +resources: + # Security group used to secure access to instances. + secgroup: + type: OS::Neutron::SecurityGroup + properties: + rules: + # Egress rule allowing access to external_subnet_cidr. + - direction: egress + ethertype: IPv4 + remote_ip_prefix: { get_param: external_subnet_cidr } + # Ingress rule, allowing also inbound access by external network. + - direction: ingress + ethertype: IPv4 + remote_ip_prefix: { get_param: external_subnet_cidr } + # Allow outbound communication with the internal subnet. + - direction: egress + ethertype: IPv4 + remote_ip_prefix: { get_param: subnet_cidr } + # Allow inbound communication from internal network. + - direction: ingress + ethertype: IPv4 + remote_ip_prefix: { get_param: subnet_cidr } + # Allow outbound access to 169.254.0.0/16, mainly for metadata. We do not need inbound. + - direction: egress + ethertype: IPv4 + remote_ip_prefix: 169.254.0.0/16 + #A network that our test environment will be connected to. + privnet: + type: OS::Neutron::Net + #Subnet that instances will live in. + privsubnet: + type: OS::Neutron::Subnet + properties: + network: { get_resource: privnet } + cidr: { get_param: subnet_cidr } + allocation_pools: + - { start: { get_param: subnet_range_start }, end: { get_param: subnet_range_end } } + gateway_ip: { get_param: router_addr } + ip_version: 4 + #A port connected to the private network, taken by router. + routerport: + type: OS::Neutron::Port + properties: + network: { get_resource: privnet } + fixed_ips: + - { subnet: { get_resource: privsubnet }, ip_address: { get_param: router_addr } } + security_groups: [{ get_resource: secgroup }] + #This is a router, routing between us and the internet. + #It has an external gateway to public network. + router: + type: OS::Neutron::Router + properties: + external_gateway_info: + network: { get_param: public_network_name } + #This is a router interface connecting it to our private subnet's router port. + routercon: + type: OS::Neutron::RouterInterface + properties: + router: { get_resource: router } + port: { get_resource: routerport } + + #Key used to authenticate to instances as root. + key: + type: OS::Nova::KeyPair + properties: + name: { get_param: "OS::stack_name" } + public_key: { get_param: auth_key } + #Handle to signal about starting up of instances. + instance_wait_handle: + type: OS::Heat::WaitConditionHandle + #Monitor waiting for all instances to start. + instance_wait: + type: OS::Heat::WaitCondition + properties: + handle: { get_resource: instance_wait_handle } + timeout: 1200 + count: + yaql: + data: { num_nodes: { get_param: num_nodes } } + #This is number of all nodes + 2 (infra instance and installer) + expression: "$.data.num_nodes + 2" + #Resource group to deploy n nodes using node template for each, each node numbered starting from 0. + nodes: + type: OS::Heat::ResourceGroup + properties: + count: { get_param: num_nodes } + resource_def: + type: node.yaml + properties: + nodenum: "%index%" + key_name: { get_resource: key } + image_name: { get_param: image_name } + network: { get_resource: privnet } + subnet: { get_resource: privsubnet } + flavor_name: { get_param: node_flavor_name } + notify_command: { get_attr: ["instance_wait_handle", "curl_cli"] } + security_group: { get_resource: secgroup } + depends_on: [routercon, instance_wait_handle] + #Nfs storage volume for first node. + nfs_storage: + type: OS::Cinder::Volume + properties: + name: nfs_storage + size: 50 + #Attachment of volume to first node. + nfs_storage_attachment: + type: OS::Cinder::VolumeAttachment + properties: + instance_uuid: { get_attr: [nodes, "resource.0"] } + volume_id: { get_resource: nfs_storage } + #Floating ip association for node (first only). + node_fip_assoc: + type: OS::Neutron::FloatingIPAssociation + properties: + floatingip_id: { get_param: node_ip } + port_id: { get_attr: ["nodes", "resource.0.port_id"] } + #Openstack volume used for storing resources. + resources_storage: + type: "OS::Cinder::Volume" + properties: + name: "resources_storage" + size: 120 + #Instance representing infrastructure instance, created using subtemplate. + infra: + type: "instance.yaml" + properties: + instance_name: infra + network: { get_resource: privnet } + subnet: { get_resource: privsubnet } + key_name: { get_resource: key } + flavor_name: { get_param: infra_flavor_name } + image_name: { get_param: image_name } + notify_command: { get_attr: ["instance_wait_handle", "curl_cli"] } + security_group: { get_resource: secgroup } + depends_on: [instance_wait_handle] + #Volume attachment for infra node. + resources_storage_attachment: + type: OS::Cinder::VolumeAttachment + properties: + volume_id: { get_resource: resources_storage } + instance_uuid: { get_resource: infra } + #Floating ip association for infra. + infra_fip_assoc: + type: OS::Neutron::FloatingIPAssociation + properties: + floatingip_id: { get_param: infra_ip } + port_id: { get_attr: ["infra", "port_id"] } + #Small installer vm having access to other instances, used to install onap. + installer: + type: "instance.yaml" + properties: + instance_name: installer + image_name: { get_param: image_name } + flavor_name: { get_param: installer_flavor_name } + key_name: { get_resource: key } + network: { get_resource: privnet } + subnet: { get_resource: privsubnet } + notify_command: { get_attr: ["instance_wait_handle", "curl_cli"] } + security_group: { get_resource: secgroup } + depends_on: instance_wait_handle + #Floating ip for installer. + installer_fip_assoc: + type: OS::Neutron::FloatingIPAssociation + properties: + floatingip_id: { get_param: installer_ip } + port_id: { get_attr: [installer, port_id] } +#Output values +outputs: + installer_ip: + value: { get_attr: [installer, ip] } + description: "Internal ip of installer instance" + infra_ip: + value: { get_attr: [infra, ip] } + description: "Internal ip of infra instance" + node_ips: + value: { get_attr: [nodes, ip] } + description: "Serialized json list of node internal ips starting at node0" + volumes: + description: "map of volumes per each instance" + value: + yaql: + data: + resources_volid: { get_resource: resources_storage } + nfs_volid: { get_resource: nfs_storage } + docker_volids: { get_attr: [nodes, docker_storage_id] } + #This is going to create a map, where keys are instance names, and values are lists of + #pairs of volume ids and their mount points. + #This is done by merging few generated maps together, base map is taken by + #enumerating over docker storage volumes and transforming them into a map like + #{"node0"=>["volid","/var/lib/docker"],...], node1=>...} + expression: 'dict($.data.docker_volids.enumerate().select(["node"+str($[0]), [[$[1], "/var/lib/docker"]]])).mergeWith({"infra" => [[$.data.resources_volid, "/opt/onap"]], "node0" => [[$.data.nfs_volid, "/dockerdata-nfs"]]})' diff --git a/tools/cicdansible/heat/instance.yaml b/tools/cicdansible/heat/instance.yaml new file mode 100644 index 00000000..2734704d --- /dev/null +++ b/tools/cicdansible/heat/instance.yaml @@ -0,0 +1,58 @@ +#Template for instances. +heat_template_version: 2017-02-24 +description: "template instantiating and configuring a single instance (any)" +parameters: + instance_name: + type: string + network: + type: string + subnet: + type: string + image_name: + type: string + flavor_name: + type: string + key_name: + type: string + notify_command: + type: string + security_group: + type: string +#Resources. +resources: + #This is the network port to attach instance to. + port: + type: OS::Neutron::Port + properties: + network: { get_param: network } + security_groups: [ { get_param: security_group } ] + fixed_ips: + - { subnet: { get_param: subnet }} + #cloudinit configuration stuff. + config: + type: OS::Heat::SoftwareConfig + properties: + config: + str_replace_strict: + template: { get_file: config.yaml } + params: + "%{NOTIFY_COMMAND}": { get_param: notify_command } + #Actual instance to create. + instance: + type: OS::Nova::Server + properties: + name: { get_param: instance_name } + image: { get_param: image_name } + flavor: { get_param: flavor_name } + key_name: { get_param: key_name } + networks: + - port: { get_resource: port } + user_data_format: SOFTWARE_CONFIG + user_data: { get_resource: config } +outputs: + OS::stack_id: + value: { get_resource: instance } + port_id: + value: { get_resource: port } + ip: + value: { get_attr: ["port", "fixed_ips", 0, "ip_address"] } diff --git a/tools/cicdansible/heat/node.yaml b/tools/cicdansible/heat/node.yaml new file mode 100644 index 00000000..b6048d8d --- /dev/null +++ b/tools/cicdansible/heat/node.yaml @@ -0,0 +1,59 @@ +#This yaml template instantiates kubernetes nodes (using instance.yaml subtemplate). +#It contains some node specific things, and has been split from main template +#to be able to do some late evaluation tricks. +heat_template_version: 2017-02-24 +description: "This template instantiates a single kubernetes node using the instance.yaml subtemplate" +parameters: + key_name: + type: string + flavor_name: + type: string + nodenum: + type: number + image_name: + type: string + network: + type: string + subnet: + type: string + notify_command: + type: string + security_group: + type: string +resources: + #Volume for storing /var/lib/docker for node. + docker_storage: + type: OS::Cinder::Volume + properties: + name: docker_storage + size: 120 + #Call generic instance template. + instance: + type: instance.yaml + properties: + instance_name: + str_replace_strict: + template: "node%index%" + params: { "%index%": { get_param: nodenum } } + key_name: { get_param: key_name } + image_name: { get_param: image_name } + network: { get_param: network } + subnet: { get_param: subnet } + flavor_name: { get_param: flavor_name } + notify_command: { get_param: notify_command } + security_group: { get_param: security_group } + #Attachment of docker volume to node. + docker_storage_attachment: + type: OS::Cinder::VolumeAttachment + properties: + volume_id: { get_resource: docker_storage } + instance_uuid: { get_resource: instance } +outputs: + OS::stack_id: + value: { get_resource: instance } + port_id: + value: { get_attr: ["instance", "port_id"] } + ip: + value: { get_attr: ["instance", "ip"] } + docker_storage_id: + value: { get_resource: docker_storage } -- cgit 1.2.3-korg From 3bf88a80668ce410b423e25a259bf4d59fd05417 Mon Sep 17 00:00:00 2001 From: Michal Zegan Date: Thu, 22 Aug 2019 14:55:16 +0200 Subject: Add inventory for cicdansible playbook This change adds the basic inventory file and group_vars used when running cicdansible playbook to deploy onap on openstack. This inventory contains only instances that must be present, other inventory entries are dynamically registered during install. Also, it delegates to group_vars for things like floating ip addresses. group_vars contains default settings for the playbook, and especially the all.yml must be modified for the environment to be deployed. Change-Id: Ia93e6b98841d7edc45699b44b2479af6daff6c4f Issue-ID: OOM-2042 Signed-off-by: Michal Zegan --- tools/cicdansible/group_vars/all.yml | 63 ++++++++++++++++++++++++++++++ tools/cicdansible/group_vars/instances.yml | 11 ++++++ tools/cicdansible/group_vars/nodes.yml | 5 +++ tools/cicdansible/group_vars/resources.yml | 6 +++ tools/cicdansible/hosts.yml | 28 +++++++++++++ 5 files changed, 113 insertions(+) create mode 100644 tools/cicdansible/group_vars/all.yml create mode 100644 tools/cicdansible/group_vars/instances.yml create mode 100644 tools/cicdansible/group_vars/nodes.yml create mode 100644 tools/cicdansible/group_vars/resources.yml create mode 100644 tools/cicdansible/hosts.yml (limited to 'tools') diff --git a/tools/cicdansible/group_vars/all.yml b/tools/cicdansible/group_vars/all.yml new file mode 100644 index 00000000..581e7c4a --- /dev/null +++ b/tools/cicdansible/group_vars/all.yml @@ -0,0 +1,63 @@ +--- +#General configuration, can be overridden in cmdline. +#Authentication/keystone url. +os_auth_url: "" +#Openstack username. +os_username: "" +#Password. +os_password: "" +#Domain name. +os_domain_name: "default" +#Project name. +os_project_name: "" +#The name or id of public network used to communicate with instances. +public_network: "" +#Floating ip address for first node instance +first_node_ip: "" +#Floating ip of infra instance. +infra_ip: "" +#Floating ip of installer. +installer_ip: "" +#Openstack flavor name for nodes. +node_flavor_name: "" +#Flavor name for infra instance. +infra_flavor_name: "" +#Flavor name for installer instance. +installer_flavor_name: "" +#Name of the image for instances. +image_name: "" +#Cidr of private subnet where instances are connected. +subnet_cidr: "10.1.0.0/24" +#Start of dhcp allocation range for subnet. +subnet_range_start: "10.1.0.4" +#Subnet allocation range end. +subnet_range_end: "10.1.0.254" +#Ip address of router used as a gateway to external network. +router_addr: "10.1.0.1" +#Cidr of external subnet to allow access to, 0.0.0.0/0 means allow internet access. +# For offline deployment it is recommended to set this to a cidr of intranet. +external_subnet_cidr: "" +#Address of cicd docker registry. +cicd_docker_registry: "" +#Number of nodes to deploy. +num_nodes: "3" +#Stack name to deploy on heat. +stack_name: "installer-test" +#Address of resource server with packages. +resource_host: "" +#Directory with all onap packages (on resource host). +resources_dir: "" +#Filename of software package. +resources_sw_filename: "sw_package.tar" +#Filename of binary resources. +resources_filename: "resources_package.tar" +#Filename of auxiliary resources. +aux_resources_filename: "aux_package.tar" +#Whether to deploy app. +#Setting it to false will skip deployment, but instance preconfiguration +#will still be done and sw resources uploaded to the installer host. +install_app: true +# This is a string containing base64-encoded yaml blob passed to offline installer via -e option. +# You can use it to override any variable in offline installer except those +# supported directly by cicdansible. +application_config: '' diff --git a/tools/cicdansible/group_vars/instances.yml b/tools/cicdansible/group_vars/instances.yml new file mode 100644 index 00000000..0d756a57 --- /dev/null +++ b/tools/cicdansible/group_vars/instances.yml @@ -0,0 +1,11 @@ +#Configuration for all instances. +#User to log in to instances as. +ansible_user: root +#Whether to become root using sudo or such like, no by default. +ansible_become: no +#Private key to use to access instances. +ansible_private_key_file: "{{ lookup('env', 'HOME') }}/.ssh/id_rsa" +#Arguments to skip host key verification for instances, modify only if you know what you are doing. +disable_ssh_host_auth: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" +ansible_ssh_common_args: "{{ disable_ssh_host_auth }}" + diff --git a/tools/cicdansible/group_vars/nodes.yml b/tools/cicdansible/group_vars/nodes.yml new file mode 100644 index 00000000..76a222c2 --- /dev/null +++ b/tools/cicdansible/group_vars/nodes.yml @@ -0,0 +1,5 @@ +#Configuration for kubernetes nodes. +#This redirects ssh connections through the installer instance, to allow connecting via internal ip. +#It should work even on openssh versions lacking -j option support. +#The value is based heavily on the default from parent group. +ansible_ssh_common_args: "{{ disable_ssh_host_auth }} -o ProxyCommand='ssh {{ disable_ssh_host_auth }} -i {{ ansible_private_key_file }} -W %h:%p root@{{ installer_ip }}'" diff --git a/tools/cicdansible/group_vars/resources.yml b/tools/cicdansible/group_vars/resources.yml new file mode 100644 index 00000000..e7c0f773 --- /dev/null +++ b/tools/cicdansible/group_vars/resources.yml @@ -0,0 +1,6 @@ +#Resource host configuration. +#Define used private key. +ansible_private_key_file: "{{ lookup('env', 'HOME') }}/.ssh/id_rsa" +#User login data. +ansible_user: root +ansible_become: no diff --git a/tools/cicdansible/hosts.yml b/tools/cicdansible/hosts.yml new file mode 100644 index 00000000..e4c416cf --- /dev/null +++ b/tools/cicdansible/hosts.yml @@ -0,0 +1,28 @@ +#Default inventory. +#This file should not be modified, instead modify group_vars. +#NOTE +#All kubernetes nodes including the first node are added to inventory dynamically. +#Instances group with children. +instances: + hosts: + +#Installer instance. + installer: + #Do not modify. + ansible_host: "{{ installer_ip }}" + +#Infra instance. + infra: + #Do not modify. + ansible_host: "{{ infra_ip }}" + + children: + #Empty group for nodes, populated dynamically, do not modify please. + nodes: + +#The group for resource host, only first entry is considered. +#This host contains onap installer packages including scripts. +resources: + hosts: + resource_host: + ansible_host: "{{ resource_host }}" -- cgit 1.2.3-korg From 60741184741db24da43fbb5846ab35eb6b00a370 Mon Sep 17 00:00:00 2001 From: Michal Zegan Date: Thu, 22 Aug 2019 14:59:55 +0200 Subject: Add floating ip fact retrieval module This change adds the ansible module that retrieves facts about floating ips, that is missing from the ansible core modules. This module is used to translate floating ips into their resource identifiers before using heat template. Change-Id: I7a8756eff30b33f82dade2f35227ff241a8c5972 Issue-ID: OOM-2042 Signed-off-by: Michal Zegan --- tools/cicdansible/library/os_floating_ips_facts.py | 61 ++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 tools/cicdansible/library/os_floating_ips_facts.py (limited to 'tools') diff --git a/tools/cicdansible/library/os_floating_ips_facts.py b/tools/cicdansible/library/os_floating_ips_facts.py new file mode 100644 index 00000000..ad546004 --- /dev/null +++ b/tools/cicdansible/library/os_floating_ips_facts.py @@ -0,0 +1,61 @@ +#!/usr/bin/python +ANSIBLE_METADATA = { + 'METADATA_VERSION': '1.1', + 'supported_by': 'community', + 'status': 'preview' +} + +DOCUMENTATION = ''' +--- +module: "os_floating_ips_facts" +short_description: "Retrieves facts about floating ips" +description: + - "This module retrieves facts about one or more floating ips allocated to project." +version_added: "2.7" +author: + - "Michal Zegan" +requirements: + - "python => 2.7" + - "openstacksdk" +options: + floating_ip: + description: + - "The floating ip to retrieve facts for" + type: "str" + network: + description: + - "Name or id of the floating ip network to query." + required: true + type: "str" +notes: + - "Registers facts starting with openstack_floating_ips" +extends_documentation_fragment: openstack +''' + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module + +def run_module(): + args=openstack_module_kwargs() + argspec=openstack_full_argument_spec( + floating_ip=dict(type=str), + network=dict(type=str, required=True)) + module=AnsibleModule(argument_spec=argspec, **args) + sdk, cloud = openstack_cloud_from_module(module) + try: + fip_network=cloud.network.find_network(module.params['network']) + filter=dict( + project_id=cloud.current_project_id, + floating_network_id=fip_network.id) + if not (module.params['floating_ip'] is None): + filter['floating_ip_address'] = module.params['floating_ip'] + ips=[dict(x) for x in cloud.network.ips(**filter)] + module.exit_json( + changed=False, + ansible_facts=dict(openstack_floating_ips=ips) + ) + except sdk.exceptions.OpenStackCloudException as e: + module.fail_json(msg=str(e)) + +if __name__ == '__main__': + run_module() -- cgit 1.2.3-korg From 02105a9808c5443542150df8e2b561ec98ebaa9e Mon Sep 17 00:00:00 2001 From: Michal Zegan Date: Thu, 22 Aug 2019 14:47:58 +0200 Subject: Add ansible role to deploy onap infrastructure on openstack This role deploys the onap infrastructure on open stack using the heat template, passing it needed parameters from inventory. It also formats and mounts all cinder volumes attached to the instances, so that they can be utilized. Change-Id: I0cb13a5b55bd31445acaa2f7c1db80a925daa5cb Issue-ID: OOM-2042 Signed-off-by: Michal Zegan --- .../tasks/configure/main.yml | 11 +++++ .../tasks/configure/volume.yml | 47 ++++++++++++++++++++++ .../tasks/deploy/heat.yml | 36 +++++++++++++++++ .../tasks/deploy/main.yml | 8 ++++ .../tasks/deploy/prereq.yml | 41 +++++++++++++++++++ .../tasks/deploy/register_instances.yml | 9 +++++ .../setup_openstack_infrastructure/tasks/main.yml | 1 + 7 files changed, 153 insertions(+) create mode 100644 tools/cicdansible/roles/setup_openstack_infrastructure/tasks/configure/main.yml create mode 100644 tools/cicdansible/roles/setup_openstack_infrastructure/tasks/configure/volume.yml create mode 100644 tools/cicdansible/roles/setup_openstack_infrastructure/tasks/deploy/heat.yml create mode 100644 tools/cicdansible/roles/setup_openstack_infrastructure/tasks/deploy/main.yml create mode 100644 tools/cicdansible/roles/setup_openstack_infrastructure/tasks/deploy/prereq.yml create mode 100644 tools/cicdansible/roles/setup_openstack_infrastructure/tasks/deploy/register_instances.yml create mode 100644 tools/cicdansible/roles/setup_openstack_infrastructure/tasks/main.yml (limited to 'tools') diff --git a/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/configure/main.yml b/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/configure/main.yml new file mode 100644 index 00000000..44de5795 --- /dev/null +++ b/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/configure/main.yml @@ -0,0 +1,11 @@ +#Openstack specific configuration running on instances. +#Get volumes. +- name: "get volume info" + set_fact: + volumes: "{{ (hostvars['localhost'].heat_stack.stack.outputs | selectattr('output_key', 'equalto', 'volumes') | list).0.output_value[inventory_hostname] | default([]) }}" +- name: "Configure volumes" + include_tasks: configure/volume.yml + vars: + volume_id: "{{ item[0] }}" + mountpoint: "{{ item[1] }}" + loop: "{{ volumes }}" diff --git a/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/configure/volume.yml b/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/configure/volume.yml new file mode 100644 index 00000000..8c553850 --- /dev/null +++ b/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/configure/volume.yml @@ -0,0 +1,47 @@ +#Configure a single openstack volume. +- name: "Set volume path" + set_fact: + volume_path: "/dev/disk/by-id/virtio-{{ volume_id | truncate(20, True, '') }}" +- name: "Set partition path" + set_fact: + partition_path: "{{ volume_path }}-part1" +- name: "Wait for volume" + #We do not do it normally, because we want to trigger udev (workaround for some bugs). + shell: "udevadm trigger && udevadm settle && [[ -b {{ volume_path }} ]]" + register: result + retries: 30 + delay: 10 + until: result.rc == 0 +- name: "Partition volume" + parted: + device: "{{ volume_path }}" + number: 1 + label: msdos + flags: boot + part_type: primary + state: present +- name: "Wait for partition to appear" + stat: + path: "{{ partition_path }}" + follow: true + register: part_stat + delay: 1 + retries: 5 + until: part_stat.stat.isblk is defined and part_stat.stat.isblk +- name: "Create xfs filesystem on volume" + filesystem: + dev: "{{ partition_path }}" + type: xfs +- name: "Ensure that the mountpoint exists" + file: + path: "{{ mountpoint }}" + owner: root + group: root + mode: 0755 + state: directory +- name: "Mount filesystem" + mount: + src: "{{ partition_path }}" + path: "{{ mountpoint }}" + fstype: xfs + state: mounted diff --git a/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/deploy/heat.yml b/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/deploy/heat.yml new file mode 100644 index 00000000..2bfeda77 --- /dev/null +++ b/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/deploy/heat.yml @@ -0,0 +1,36 @@ +#Tasks for stack redeployment. +#Delete the heat stack before deployment. +- name: "delete deployment to force redeploy" + os_stack: + auth: "{{ os_auth }}" + auth_type: token + name: "{{ stack_name }}" + state: absent +#Deploy heat stack with infrastructure. +- name: "Deploy the infrastructure via heat" + os_stack: + auth: "{{ os_auth }}" + auth_type: token + name: "{{ stack_name }}" + template: "heat/installer.yaml" + state: present + environment: + - "heat/installer.env" + parameters: + num_nodes: "{{ num_nodes }}" + public_network_name: "{{ public_network }}" + external_subnet_cidr: "{{ external_subnet_cidr }}" + subnet_cidr: "{{ subnet_cidr }}" + subnet_range_start: "{{ subnet_range_start }}" + subnet_range_end: "{{ subnet_range_end }}" + router_addr: "{{ router_addr }}" + auth_key: "{{ auth_public_key }}" + image_name: "{{ image_name }}" + node_flavor_name: "{{ node_flavor_name }}" + infra_flavor_name: "{{ infra_flavor_name }}" + installer_flavor_name: "{{ installer_flavor_name }}" + node_ip: "{{ floating_ips_by_address[first_node_ip].id }}" + infra_ip: "{{ floating_ips_by_address[infra_ip].id }}" + installer_ip: "{{ floating_ips_by_address[installer_ip].id }}" + wait: true + register: heat_stack diff --git a/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/deploy/main.yml b/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/deploy/main.yml new file mode 100644 index 00000000..324f5374 --- /dev/null +++ b/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/deploy/main.yml @@ -0,0 +1,8 @@ +--- +#This mode expects some variables, and deploys infrastructure on open stack. +#Execute prerequisites. +- include_tasks: deploy/prereq.yml +#Deploy stack. +- include_tasks: deploy/heat.yml +#Register instances in inventory. +- include_tasks: deploy/register_instances.yml diff --git a/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/deploy/prereq.yml b/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/deploy/prereq.yml new file mode 100644 index 00000000..2fe8717a --- /dev/null +++ b/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/deploy/prereq.yml @@ -0,0 +1,41 @@ +#Prerequisite tasks before stack deployment. +#Authenticate to cloud. +- name: "authenticate to cloud" + os_auth: + auth: + auth_url: "{{ os_auth_url }}" + username: "{{ os_username }}" + password: "{{ os_password }}" + domain_name: "{{ os_domain_name }}" + project_name: "{{ os_project_name }}" + project_domain_name: "{{ os_domain_name }}" +#Will use the token from this point on. +- name: "set token" + set_fact: + os_auth: + auth_url: "{{ os_auth_url }}" + token: "{{ auth_token }}" + project_name: "{{ os_project_name }}" + project_domain_name: "{{ os_domain_name }}" +#Retrieve floating ip info. +- name: "get floating ip facts" + os_floating_ips_facts: + auth: "{{ os_auth }}" + auth_type: token + network: "{{ public_network }}" +#Group floating ips by ip address to allow looking them up. +- name: "group floating ips by address" + set_fact: + floating_ips_by_address: "{{ floating_ips_by_address | default({}) | combine({item.floating_ip_address: item}) }}" + loop: "{{ query('items', openstack_floating_ips) }}" +- name: "fail if required floating ips do not exist" + fail: msg="The required floating ips do not exist" + when: "(not (first_node_ip in floating_ips_by_address) + or not (infra_ip in floating_ips_by_address) + or not (installer_ip in floating_ips_by_address))" +#Get a ssh public key to be passed to heat, it requires ssh-keygen with -y option. +- name: "Retrieve public key from ssh private key" + command: "ssh-keygen -y -f {{ hostvars['installer'].ansible_private_key_file }}" + register: public_key_generation +- set_fact: + auth_public_key: "{{ public_key_generation.stdout }}" diff --git a/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/deploy/register_instances.yml b/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/deploy/register_instances.yml new file mode 100644 index 00000000..a50ecd22 --- /dev/null +++ b/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/deploy/register_instances.yml @@ -0,0 +1,9 @@ +#Register instances as hosts in inventory. +#Installer and infra are statically registered. +#Register node instances dynamically. +- name: "Register node instances" + add_host: + name: "node{{ item[0] }}" + groups: nodes + ansible_host: "{{ item[1] }}" + loop: "{{ query('indexed_items', (heat_stack.stack.outputs | selectattr('output_key', 'equalto', 'node_ips') | list).0.output_value) }}" diff --git a/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/main.yml b/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/main.yml new file mode 100644 index 00000000..7a00abff --- /dev/null +++ b/tools/cicdansible/roles/setup_openstack_infrastructure/tasks/main.yml @@ -0,0 +1 @@ +- include_tasks: "{{ mode }}/main.yml" -- cgit 1.2.3-korg From 8944150190575aaa2925b68fad0678719d2baffe Mon Sep 17 00:00:00 2001 From: Michal Zegan Date: Thu, 22 Aug 2019 14:50:22 +0200 Subject: Add onap instance configuration role This change adds a role that configures deployed onap infrastructure instances. This role is generic and not openstack dependent. This role configures instances to reach each other by name, to mutually authenticate with the given ssh keys, etc. This mainly makes it easier for developers to do troubleshooting, and allows offline installer to work smoothly. Change-Id: I26750b0a8a69f56297f0a5f7ff491463ed2e9e32 Issue-ID: OOM-2042 Signed-off-by: Michal Zegan --- .../configure_instances/tasks/cicd_registry.yml | 10 +++++++++ .../roles/configure_instances/tasks/general.yml | 26 ++++++++++++++++++++++ .../roles/configure_instances/tasks/main.yml | 5 +++++ .../configure_instances/templates/daemon.json.j2 | 3 +++ 4 files changed, 44 insertions(+) create mode 100644 tools/cicdansible/roles/configure_instances/tasks/cicd_registry.yml create mode 100644 tools/cicdansible/roles/configure_instances/tasks/general.yml create mode 100644 tools/cicdansible/roles/configure_instances/tasks/main.yml create mode 100644 tools/cicdansible/roles/configure_instances/templates/daemon.json.j2 (limited to 'tools') diff --git a/tools/cicdansible/roles/configure_instances/tasks/cicd_registry.yml b/tools/cicdansible/roles/configure_instances/tasks/cicd_registry.yml new file mode 100644 index 00000000..f3c54ca3 --- /dev/null +++ b/tools/cicdansible/roles/configure_instances/tasks/cicd_registry.yml @@ -0,0 +1,10 @@ +#Configure access to cicd docker registry. +- name: "Ensure that docker config directory exists" + file: + path: /etc/docker + mode: 0700 + state: directory +- name: "Allow insecure access to cicd docker registry" + template: + src: daemon.json.j2 + dest: /etc/docker/daemon.json diff --git a/tools/cicdansible/roles/configure_instances/tasks/general.yml b/tools/cicdansible/roles/configure_instances/tasks/general.yml new file mode 100644 index 00000000..6ed9982e --- /dev/null +++ b/tools/cicdansible/roles/configure_instances/tasks/general.yml @@ -0,0 +1,26 @@ +#General instance configuration. +#Modify /etc/hosts on every instance to add every instance there including itself. +- name: "Add hosts to /etc/hosts" + lineinfile: + path: /etc/hosts + insertafter: EOF + regexp: "^[^ ]+ {{ item }}$" + state: present + line: "{{ hostvars[item].ansible_default_ipv4.address }} {{ item }}" + loop: "{{ groups['instances'] }}" +#Copy private ssh key to instances for easy connecting between them. +- name: "Ensure ssh directory exists" + file: + path: /root/.ssh + owner: root + group: root + mode: 0700 + state: directory +- name: "Install ssh private key" + copy: + src: "{{ ansible_private_key_file }}" + dest: /root/.ssh/id_rsa + mode: 0400 +#Add public ssh host keys of all instances to trust them. +- name: "Add host keys of instances to known_hosts" + shell: "ssh-keyscan {{ groups['instances'] | join(' ') }} > /root/.ssh/known_hosts" diff --git a/tools/cicdansible/roles/configure_instances/tasks/main.yml b/tools/cicdansible/roles/configure_instances/tasks/main.yml new file mode 100644 index 00000000..fe5b4b7d --- /dev/null +++ b/tools/cicdansible/roles/configure_instances/tasks/main.yml @@ -0,0 +1,5 @@ +#Initial instance configuration. +- include_tasks: general.yml +#Configure cicd registry access, but skip installer. +- include_tasks: cicd_registry.yml + when: "inventory_hostname != 'installer'" diff --git a/tools/cicdansible/roles/configure_instances/templates/daemon.json.j2 b/tools/cicdansible/roles/configure_instances/templates/daemon.json.j2 new file mode 100644 index 00000000..1c3ca9bb --- /dev/null +++ b/tools/cicdansible/roles/configure_instances/templates/daemon.json.j2 @@ -0,0 +1,3 @@ +{ +"insecure-registries": ["{{ cicd_docker_registry }}"] +} -- cgit 1.2.3-korg From 10fef61184e957c6397f2354666698f68a0926dd Mon Sep 17 00:00:00 2001 From: Michal Zegan Date: Thu, 22 Aug 2019 14:53:46 +0200 Subject: Add onap installation role This role generates offline installer parameters and inventory, downloads offline installer sw package, and initiates onap installation, waiting for it to finish. Change-Id: I5c79d9732b8d77f57278f5009f4e5089377fc2cf Issue-ID: OOM-2042 Signed-off-by: Michal Zegan --- tools/cicdansible/roles/install/defaults/main.yml | 3 ++ .../roles/install/tasks/download_resources.yml | 6 +++ tools/cicdansible/roles/install/tasks/install.yml | 48 ++++++++++++++++++++++ tools/cicdansible/roles/install/tasks/main.yml | 1 + .../roles/install/templates/inventory.yml.j2 | 36 ++++++++++++++++ 5 files changed, 94 insertions(+) create mode 100644 tools/cicdansible/roles/install/defaults/main.yml create mode 100644 tools/cicdansible/roles/install/tasks/download_resources.yml create mode 100644 tools/cicdansible/roles/install/tasks/install.yml create mode 100644 tools/cicdansible/roles/install/tasks/main.yml create mode 100644 tools/cicdansible/roles/install/templates/inventory.yml.j2 (limited to 'tools') diff --git a/tools/cicdansible/roles/install/defaults/main.yml b/tools/cicdansible/roles/install/defaults/main.yml new file mode 100644 index 00000000..b21e6323 --- /dev/null +++ b/tools/cicdansible/roles/install/defaults/main.yml @@ -0,0 +1,3 @@ +--- +installer_deploy_path: "{{ ansible_user_dir }}/installer" +install_timeout: 10600 diff --git a/tools/cicdansible/roles/install/tasks/download_resources.yml b/tools/cicdansible/roles/install/tasks/download_resources.yml new file mode 100644 index 00000000..7f042596 --- /dev/null +++ b/tools/cicdansible/roles/install/tasks/download_resources.yml @@ -0,0 +1,6 @@ +#Download resources/scripts to controller. +- name: "Download software resources" + fetch: + src: "{{ resources_dir }}/{{ resources_sw_filename }}" + flat: yes + dest: "resources/" diff --git a/tools/cicdansible/roles/install/tasks/install.yml b/tools/cicdansible/roles/install/tasks/install.yml new file mode 100644 index 00000000..35df7976 --- /dev/null +++ b/tools/cicdansible/roles/install/tasks/install.yml @@ -0,0 +1,48 @@ +#Onap installation tasks +#Copy ssh private key used for resource server access +- name: "Copy resource server access key" + copy: + src: "{{ hostvars[groups['resources'][0]].ansible_private_key_file }}" + dest: "{{ ansible_user_dir }}/.ssh/res.pem" + mode: 0600 +#Unarchive resources. +- name: "Ensure {{ installer_deploy_path }} directory exists" + file: + path: "{{ installer_deploy_path }}" + state: directory +- name: "Extract sw resources" + unarchive: + src: "resources/{{ hostvars[groups['resources'][0]].resources_sw_filename }}" + dest: "{{ installer_deploy_path }}" +#Generate ansible inventory and extra vars. +- name: "Generate ansible inventory for installer" + template: + src: inventory.yml.j2 + dest: "{{ installer_deploy_path }}/ansible/inventory/hosts.yml" +- name: "generate application specific config overrides" + copy: + content: "{{ application_config | b64decode }}" + dest: "{{ installer_deploy_path }}/ansible/application/application_overrides.yml" +# This generates a file with locations of resource files in resource host, we +# do it only to allow manually running offline installer without +# typing them by hand. We cannot use +# inventory template because it will be overridden +# by application_configuration.yml. +- name: Generate resource location file + copy: + content: | + resources_dir: {{ resources_dir }} + resources_filename: {{ resources_filename }} + aux_resources_filename: {{ aux_resources_filename }} + app_data_path: /opt/onap/resources + dest: "{{ installer_deploy_path }}/ansible/application/resources.yml" +#Run script. +- name: "Execute installation" + shell: + ./run_playbook.sh + -e @application/application_configuration.yml -e @application/application_overrides.yml + -e @application/resources.yml -i inventory/hosts.yml site.yml + args: + chdir: "{{ installer_deploy_path }}/ansible" + async: "{{ install_timeout }}" + when: install_app diff --git a/tools/cicdansible/roles/install/tasks/main.yml b/tools/cicdansible/roles/install/tasks/main.yml new file mode 100644 index 00000000..04ac4c3d --- /dev/null +++ b/tools/cicdansible/roles/install/tasks/main.yml @@ -0,0 +1 @@ +- include_tasks: "{{ mode }}.yml" diff --git a/tools/cicdansible/roles/install/templates/inventory.yml.j2 b/tools/cicdansible/roles/install/templates/inventory.yml.j2 new file mode 100644 index 00000000..36bf3bd3 --- /dev/null +++ b/tools/cicdansible/roles/install/templates/inventory.yml.j2 @@ -0,0 +1,36 @@ +all: + vars: + ansible_ssh_private_key_file: /root/.ssh/id_rsa + ansible_ssh_common_args: "-o StrictHostKeyChecking=no" + children: + resources: + vars: + ansible_ssh_private_key_file: /root/.ssh/res.pem + ansible_user: "{{ hostvars[groups['resources'][0]].ansible_user }}" + ansible_become: "{{ hostvars[groups['resources'][0]].ansible_become }}" + hosts: + resource_host: + ansible_host: {{ resource_host }} + infrastructure: + hosts: + infra_host: + ansible_host: infra + cluster_ip: {{ hostvars['infra'].ansible_default_ipv4.address }} + kubernetes: + children: + kubernetes-node: + hosts: +{% for h in groups['nodes'] %} + {{ h }}: + ansible_host: "{{ hostvars[h].ansible_default_ipv4.address }}" + cluster_ip: "{{ hostvars[h].ansible_default_ipv4.address }}" +{% endfor %} + kubernetes-control-plane: + hosts: + infra_host + kubernetes-etcd: + hosts: + infra_host + nfs-server: + hosts: + node0 -- cgit 1.2.3-korg From e465912f7a9d5088f06bd7d0a9bb60c010b05968 Mon Sep 17 00:00:00 2001 From: Michal Zegan Date: Thu, 22 Aug 2019 14:58:40 +0200 Subject: Add cicdansible playbook This playbook runs the cicdansible roles on hosts defined, statically or dynamically, in the inventory. It deploys onap infrastructure on openstack, then installs onap. Change-Id: Idf618ff137c1adbad8f9b2f1bf878eaa9f20465d Issue-ID: OOM-2042 Signed-off-by: Michal Zegan --- tools/cicdansible/install.yml | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tools/cicdansible/install.yml (limited to 'tools') diff --git a/tools/cicdansible/install.yml b/tools/cicdansible/install.yml new file mode 100644 index 00000000..13071c31 --- /dev/null +++ b/tools/cicdansible/install.yml @@ -0,0 +1,36 @@ +--- +#Installation of onap on open stack driven by ansible. +#Default parameters are set in group_vars/*.yml. +#Inventory is in hosts.yml, and parameters specific to instances are set there. +#Deploy infrastructure. +- name: "deploy infrastructure" + hosts: localhost + gather_facts: false + roles: + - role: setup_openstack_infrastructure + vars: + mode: deploy +#Play that configures all instances. +- name: "Instance configuration" + hosts: instances + any_errors_fatal: true + roles: + - role: setup_openstack_infrastructure + vars: + mode: configure + - role: configure_instances +#Play that downloads sw resources. +- name: "Download resources" + hosts: resources + gather_facts: false + roles: + - role: install + vars: + mode: download_resources +#Perform installation. +- name: "Perform installation" + hosts: installer + roles: + - role: install + vars: + mode: install -- cgit 1.2.3-korg From 2e34522351d40edd0e37b4919630736748949f2a Mon Sep 17 00:00:00 2001 From: Michal Zegan Date: Thu, 22 Aug 2019 15:01:07 +0200 Subject: Add ansible configuration file This commit adds the ansible configuration file, that configures pretty logging and, handling of connections and inventory, etc to make the playbook nicer to use. Change-Id: Ibf9eded62f87d338b4b215e8b0b37d80ec86b219 Issue-ID: OOM-2042 Signed-off-by: Michal Zegan --- tools/cicdansible/ansible.cfg | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tools/cicdansible/ansible.cfg (limited to 'tools') diff --git a/tools/cicdansible/ansible.cfg b/tools/cicdansible/ansible.cfg new file mode 100644 index 00000000..e74dda58 --- /dev/null +++ b/tools/cicdansible/ansible.cfg @@ -0,0 +1,18 @@ +#Ansible configuration used when running the playbook. +[defaults] +#Stdout callback. +stdout_callback=debug +#Default verbosity level, for logging all module outputs. +verbosity=1 + +[inventory] +#Fail when inventory parsing fails. +any_unparsed_is_failed=true + +[connection] +#Enable ansible pipelining. +pipelining=true + +[ssh_connection] +#Increase control persist settings. +ssh_args=-C -o ControlMaster=auto -o ControlPersist=30m -- cgit 1.2.3-korg