diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml index ef6ccc7d6b4dcdae63390134f3e68fd38c2bc393..992eb4b2d91549dbb2b7867969bef001a442db32 100644 --- a/ansible/group_vars/all.yml +++ b/ansible/group_vars/all.yml @@ -122,7 +122,7 @@ bifrost_network_interface: "{{ network_interface }}" dns_interface: "{{ network_interface }}" tunnel_interface_address: "{{ hostvars[inventory_hostname]['ansible_' + tunnel_interface]['ipv4']['address'] }}" -# Valid options are [ openvswitch, linuxbridge, vmware_nsxv, vmware_dvs ] +# Valid options are [ openvswitch, linuxbridge, vmware_nsxv, vmware_dvs, opendaylight ] neutron_plugin_agent: "openvswitch" # The default ports used by each service. @@ -260,6 +260,19 @@ watcher_api_port: "9322" zun_api_port: "9517" +opendaylight_clustering_port: "2550" +opendaylight_restconf_port: "8087" +opendaylight_restconf_port_backup: "8182" +opendaylight_haproxy_restconf_port: "8088" +opendaylight_haproxy_restconf_port_backup: "8183" +opendaylight_jetty_conf_port: "8543" +opendaylight_jetty_conf2_port: "8443" +opendaylight_tomcat_port: "8282" +opendaylight_tomcat_redirect_port: "8663" +opendaylight_karaf_ssh_port: "8101" +opendaylight_openflow_port: "6653" +opendaylight_ovsdb_port: "6641" +opendaylight_haproxy_ovsdb_port: "6642" public_protocol: "{{ 'https' if kolla_enable_tls_external | bool else 'http' }}" internal_protocol: "http" @@ -375,6 +388,7 @@ enable_neutron_provider_networks: "no" enable_neutron_sfc: "no" enable_nova_serialconsole_proxy: "no" enable_octavia: "no" +enable_opendaylight: "no" enable_openvswitch: "{{ neutron_plugin_agent != 'linuxbridge' | bool }}" enable_osprofiler: "no" enable_panko: "no" @@ -530,7 +544,7 @@ neutron_type_drivers: "flat,vlan,vxlan" # NOTE: for ironic this list should also contain 'flat' neutron_tenant_network_types: "vxlan" -computes_need_external_bridge: "{{ enable_neutron_dvr | bool or enable_neutron_provider_networks | bool and neutron_plugin_agent != 'vmware_dvs' }}" +computes_need_external_bridge: "{{ enable_neutron_dvr | bool or enable_neutron_provider_networks | bool or enable_opendaylight | bool and neutron_plugin_agent != 'vmware_dvs' }}" ####################### # Nova options @@ -612,3 +626,17 @@ vmware_vcenter_host_ip: vmware_vcenter_host_username: vmware_vcenter_host_password: vmware_vcenter_cluster_name: + +###################### +# OpenDaylight +###################### +opendaylight_release: "0.6.1-Carbon" +opendaylight_mechanism_driver: "opendaylight_v2" +opendaylight_l3_service_plugin: "odl-router_v2" +opendaylight_acl_impl: "learn" +enable_opendaylight_qos: "no" +enable_opendaylight_l3: "{{ enable_opendaylight }}" +enable_opendaylight_legacy_netvirt_conntrack: "no" +opendaylight_port_binding_type: "pseudo-agentdb-binding" +opendaylight_features: "odl-mdsal-apidocs,odl-netvirt-openstack" +opendaylight_allowed_network_types: '"flat", "vlan", "vxlan"' diff --git a/ansible/inventory/all-in-one b/ansible/inventory/all-in-one index 154abf5e6f60455638529ddb08b91fedd05029cc..f9c6de918bea49599bfdd0a52b787d979afd4a58 100644 --- a/ansible/inventory/all-in-one +++ b/ansible/inventory/all-in-one @@ -103,6 +103,9 @@ network compute manila-share +[opendaylight:children] +network + [cinder:children] control diff --git a/ansible/inventory/multinode b/ansible/inventory/multinode index 8b57b3d4d1607287e2fcd11fee1149be5a52791a..c319219ce3d07fbc330f329d35c3ab9cb5446b0e 100644 --- a/ansible/inventory/multinode +++ b/ansible/inventory/multinode @@ -124,6 +124,9 @@ network compute manila-share +[opendaylight:children] +network + [cinder:children] control diff --git a/ansible/roles/haproxy/templates/haproxy.cfg.j2 b/ansible/roles/haproxy/templates/haproxy.cfg.j2 index 49c7e029d4efd9eacc82df564f5d266372e8c5f1..bdde3f92da776f4d079c69f2b823d7a34f8c2d11 100644 --- a/ansible/roles/haproxy/templates/haproxy.cfg.j2 +++ b/ansible/roles/haproxy/templates/haproxy.cfg.j2 @@ -873,3 +873,30 @@ listen mariadb {% endfor %} {% endif %} +{% if enable_opendaylight | bool %} +listen opendaylight_api + bind {{ kolla_internal_vip_address }}:{{ opendaylight_haproxy_restconf_port }} + balance source +{% for host in groups['opendaylight'] %} + server {{ hostvars[host]['ansible_hostname'] }} {{ hostvars[host]['ansible_' + hostvars[host]['api_interface']]['ipv4']['address'] }}:{{ opendaylight_restconf_port }} check fall 5 inter 2000 rise 2 +{% endfor %} + +listen opendaylight_api_backup + bind {{ kolla_internal_vip_address }}:{{ opendaylight_haproxy_restconf_port_backup }} + balance source +{% for host in groups['opendaylight'] %} + server {{ hostvars[host]['ansible_hostname'] }} {{ hostvars[host]['ansible_' + hostvars[host]['api_interface']]['ipv4']['address'] }}:{{ opendaylight_restconf_port_backup }} check fall 5 inter 2000 rise 2 +{% endfor %} + +listen opendaylight_ovsdb + mode tcp + timeout client 3600s + timeout server 3600s + option tcplog + option tcpka + bind {{ kolla_internal_vip_address }}:{{ opendaylight_haproxy_ovsdb_port }} +{% for host in groups['opendaylight'] %} + server {{ hostvars[host]['ansible_hostname'] }} {{ hostvars[host]['ansible_' + hostvars[host]['api_interface']]['ipv4']['address'] }}:{{ opendaylight_ovsdb_port }} check inter 2000 rise 2 fall 5 {% if not loop.first %}backup{% endif %} + +{% endfor %} +{% endif %} diff --git a/ansible/roles/neutron/defaults/main.yml b/ansible/roles/neutron/defaults/main.yml index f24ab2b4aa95a4ddc3dc89434cfcf6ddc92f2475..e52d60a692cd615b8c86a795f4aac94b6f50a3ea 100644 --- a/ansible/roles/neutron/defaults/main.yml +++ b/ansible/roles/neutron/defaults/main.yml @@ -81,7 +81,7 @@ neutron_services: container_name: "neutron_l3_agent" image: "{{ neutron_l3_agent_image_full }}" privileged: True - enabled: "{{ not enable_neutron_vpnaas | bool and neutron_plugin_agent not in ['vmware_nsxv', 'vmware_dvs'] }}" + enabled: "{{ not enable_neutron_vpnaas | bool and neutron_plugin_agent not in ['vmware_nsxv', 'vmware_dvs'] and not enable_opendaylight_l3 | bool }}" host_in_groups: >- {{ inventory_hostname in groups['neutron-l3-agent'] @@ -90,6 +90,7 @@ neutron_services: volumes: - "{{ node_config_directory }}/neutron-l3-agent/:{{ container_config_directory }}/:ro" - "/etc/localtime:/etc/localtime:ro" + - "/lib/modules:/lib/modules:ro" - "/run:/run:shared" - "neutron_metadata_socket:/var/lib/neutron/kolla/" - "kolla_logs:/var/log/kolla/" @@ -186,7 +187,7 @@ neutron_openvswitch_agent_image: "{{ docker_registry ~ '/' if docker_registry el neutron_openvswitch_agent_tag: "{{ neutron_tag }}" neutron_openvswitch_agent_image_full: "{{ neutron_openvswitch_agent_image }}:{{ neutron_openvswitch_agent_tag }}" -neutron_server_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ neutron_install_type }}-neutron-server" +neutron_server_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ neutron_install_type }}-neutron-server{{ '-opendaylight' if enable_opendaylight | bool else '' }}" neutron_server_tag: "{{ neutron_tag }}" neutron_server_image_full: "{{ neutron_server_image }}:{{ neutron_server_tag }}" @@ -218,7 +219,7 @@ openstack_neutron_auth: "{{ openstack_auth }}" #################### extension_drivers: - name: "qos" - enabled: "{{ enable_neutron_qos | bool }}" + enabled: "{{ enable_neutron_qos | bool or enable_opendaylight_qos | bool }}" - name: "port_security" enabled: true - name: "dns" @@ -241,13 +242,15 @@ service_plugins: - name: "vpnaas" enabled: "{{ enable_neutron_vpnaas | bool }}" - name: "qos" - enabled: "{{ enable_neutron_qos | bool }}" + enabled: "{{ enable_neutron_qos | bool or enable_opendaylight_qos | bool}}" - name: "router" - enabled: true + enabled: "{{ not enable_opendaylight_l3 | bool }}" - name: "sfc" enabled: "{{ enable_neutron_sfc | bool }}" - name: "neutron_dynamic_routing.services.bgp.bgp_plugin.BgpPlugin" enabled: "{{ enable_neutron_bgp_dragent | bool }}" + - name: "{{ opendaylight_l3_service_plugin }}" + enabled: "{{ enable_opendaylight_l3 | bool and enable_opendaylight | bool }}" neutron_service_plugins: "{{ service_plugins|selectattr('enabled', 'equalto', true)|list }}" @@ -302,3 +305,12 @@ vmware_dvs_host_password: "password" vmware_dvs_insecure: "True" vmware_dvs_dvs_name: "VDS-1" vmware_dvs_dhcp_override_mac: "" + +###################### +# Notification Drivers +###################### +notification_drivers: + - name: "odl-qos-v2" + enabled: "{{ enable_opendaylight_qos | bool }}" + +neutron_notification_drivers: "{{ notification_drivers|selectattr('enabled', 'equalto', true)|list }}" diff --git a/ansible/roles/neutron/templates/dhcp_agent.ini.j2 b/ansible/roles/neutron/templates/dhcp_agent.ini.j2 index 71c40967ccba3f89dce1401dc19a4ea63c44e055..240482db440bea1de26a624513ea70b5b1dfa77c 100644 --- a/ansible/roles/neutron/templates/dhcp_agent.ini.j2 +++ b/ansible/roles/neutron/templates/dhcp_agent.ini.j2 @@ -16,6 +16,10 @@ dhcp_override_mac = {{ vmware_dvs_dhcp_override_mac }} {% endif %} {% endif %} +{% if enable_opendaylight | bool %} +interface_driver = openvswitch +{% endif %} + [ovs] ovsdb_interface = native ovsdb_connection = tcp:{{ api_interface_address }}:6640 diff --git a/ansible/roles/neutron/templates/ml2_conf.ini.j2 b/ansible/roles/neutron/templates/ml2_conf.ini.j2 index 054b8faa43b55fa293c90197be5756eb70ca4209..279423ba3a2b9fbf017e3bf863a02398213d8609 100644 --- a/ansible/roles/neutron/templates/ml2_conf.ini.j2 +++ b/ansible/roles/neutron/templates/ml2_conf.ini.j2 @@ -12,6 +12,8 @@ mechanism_drivers = openvswitch,l2population {% endif %} {% elif neutron_plugin_agent == "linuxbridge" %} mechanism_drivers = linuxbridge,l2population +{% elif neutron_plugin_agent == "opendaylight" %} +mechanism_drivers = {{ opendaylight_mechanism_driver }} {% endif %} {% if neutron_extension_drivers %} @@ -20,6 +22,14 @@ extension_drivers = {{ neutron_extension_drivers|map(attribute='name')|join(',') extension_drivers = port_security {% endif %} +{% if enable_opendaylight | bool %} +[ml2_odl] +url = {{ internal_protocol }}://{{ kolla_internal_vip_address }}:{{ opendaylight_haproxy_restconf_port }}/controller/nb/v2/neutron +username = admin +password = {{ opendaylight_password }} +port_binding_controller = {{ opendaylight_port_binding_type }} +{% endif %} + [ml2_type_vlan] {% if enable_ironic | bool %} network_vlan_ranges = physnet1 @@ -41,13 +51,13 @@ vxlan_group = 239.1.1.1 {% endif %} [securitygroup] -{% if neutron_plugin_agent == "openvswitch" %} +{% if neutron_plugin_agent == "openvswitch" or neutron_plugin_agent == "opendaylight" %} firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver {% elif neutron_plugin_agent == "linuxbridge" %} firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver {% endif %} -{% if neutron_plugin_agent == "openvswitch" %} +{% if neutron_plugin_agent == "openvswitch" or neutron_plugin_agent == "opendaylight" %} {% if not enable_hyperv | bool %} [agent] tunnel_types = vxlan diff --git a/ansible/roles/neutron/templates/neutron-server.json.j2 b/ansible/roles/neutron/templates/neutron-server.json.j2 index 076e9a5eaed650776b10784377daec21160b2c89..9f83c71f9da1cb3d2f99905357d64f7acc88340d 100644 --- a/ansible/roles/neutron/templates/neutron-server.json.j2 +++ b/ansible/roles/neutron/templates/neutron-server.json.j2 @@ -1,5 +1,5 @@ { - "command": "neutron-server --config-file /etc/neutron/neutron.conf {% if neutron_plugin_agent in ['openvswitch', 'linuxbridge'] %} --config-file /etc/neutron/plugins/ml2/ml2_conf.ini --config-file /etc/neutron/neutron_lbaas.conf --config-file /etc/neutron/neutron_vpnaas.conf {% elif neutron_plugin_agent in ['vmware_nsx', 'vmware_dvs'] %} --config-file /etc/neutron/plugins/vmware/nsx.ini {% endif %} --config-file /etc/neutron/fwaas_driver.ini", + "command": "neutron-server --config-file /etc/neutron/neutron.conf {% if neutron_plugin_agent in ['openvswitch', 'linuxbridge', 'opendaylight'] %} --config-file /etc/neutron/plugins/ml2/ml2_conf.ini --config-file /etc/neutron/neutron_lbaas.conf --config-file /etc/neutron/neutron_vpnaas.conf {% elif neutron_plugin_agent in ['vmware_nsx', 'vmware_dvs'] %} --config-file /etc/neutron/plugins/vmware/nsx.ini {% endif %} --config-file /etc/neutron/fwaas_driver.ini", "config_files": [ { "source": "{{ container_config_directory }}/neutron.conf", diff --git a/ansible/roles/neutron/templates/neutron.conf.j2 b/ansible/roles/neutron/templates/neutron.conf.j2 index 919c7422c6f70e85accd5542850e6656cd511e87..d1aa1d8681c83b9884ab21a7357c19e8aee4ee2e 100644 --- a/ansible/roles/neutron/templates/neutron.conf.j2 +++ b/ansible/roles/neutron/templates/neutron.conf.j2 @@ -24,7 +24,7 @@ rpc_state_report_workers = {{ openstack_service_rpc_workers }} # in it is because we are sharing this socket in a volume which is it's own dir metadata_proxy_socket = /var/lib/neutron/kolla/metadata_proxy -{% if neutron_plugin_agent == "openvswitch" %} +{% if neutron_plugin_agent == "openvswitch" or neutron_plugin_agent == "opendaylight" %} interface_driver = openvswitch {% elif neutron_plugin_agent == "linuxbridge" %} interface_driver = linuxbridge @@ -145,3 +145,8 @@ hmac_keys = {{ osprofiler_secret }} connection_string = elasticsearch://{{ elasticsearch_address }}:{{ elasticsearch_port }} {% endif %} {% endif %} + +{% if enable_opendaylight_qos | bool %} +[qos] +notification_drivers = {{ neutron_notification_drivers|map(attribute='name')|join(',') }} +{% endif %} diff --git a/ansible/roles/opendaylight/defaults/main.yml b/ansible/roles/opendaylight/defaults/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..f2d35bda472d8233705807a33b3684ba09e8c41f --- /dev/null +++ b/ansible/roles/opendaylight/defaults/main.yml @@ -0,0 +1,24 @@ +--- +project_name: "opendaylight" + +opendaylight_services: + opendaylight: + container_name: "opendaylight" + image: "{{ opendaylight_image_full }}" + enabled: True + privileged: True + group: "opendaylight" + host_in_groups: "{{ inventory_hostname in groups['opendaylight'] }}" + volumes: + - "{{ node_config_directory }}/opendaylight/:{{ container_config_directory }}/:ro" + - "/etc/localtime:/etc/localtime:ro" + - "kolla_logs:/var/log/kolla/" + +#################### +# Docker +#################### + +opendaylight_install_type: "{{ kolla_install_type }}" +opendaylight_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ opendaylight_install_type }}-opendaylight" +opendaylight_tag: "{{ openstack_release }}" +opendaylight_image_full: "{{ opendaylight_image }}:{{ opendaylight_tag }}" diff --git a/ansible/roles/opendaylight/handlers/main.yml b/ansible/roles/opendaylight/handlers/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..0a5f9eec70eae0f61486226c0b3bb0ae0f235750 --- /dev/null +++ b/ansible/roles/opendaylight/handlers/main.yml @@ -0,0 +1,31 @@ +--- +- name: Restart opendaylight container + vars: + service_name: "opendaylight" + service: "{{ opendaylight_services[service_name] }}" + kolla_docker: + action: "recreate_or_restart_container" + common_options: "{{ docker_common_options }}" + name: "{{ service.container_name }}" + image: "{{ service.image }}" + volumes: "{{ service.volumes }}" + privileged: "{{ service.privileged | default(False) }}" + when: + - action != "config" + - service.enabled | bool + - service.host_in_groups | bool + - opendaylight_config_json | changed + or opendaylight_config_start_odl | changed + or opendaylight_config_custom_props | changed + or opendaylight_config_jetty | changed + or opendaylight_config_features | changed + or opendaylight_config_ovsdb | changed + or opendaylight_config_tomcat | changed + or opendaylight_config_logging | changed + or opendaylight_config_netvirt | changed + or opendaylight_config_netvirt_acl | changed + or opendaylight_config_env | changed + or opendaylight_config_akka | changed + or opendaylight_config_modules | changed + or opendaylight_config_module_shards | changed + or check_opendaylight_containers | changed diff --git a/ansible/roles/opendaylight/meta/main.yml b/ansible/roles/opendaylight/meta/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..6b4fff8fef6f81d35b73a30c90de45639db41cc9 --- /dev/null +++ b/ansible/roles/opendaylight/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - { role: common } diff --git a/ansible/roles/opendaylight/tasks/check.yml b/ansible/roles/opendaylight/tasks/check.yml new file mode 100644 index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd --- /dev/null +++ b/ansible/roles/opendaylight/tasks/check.yml @@ -0,0 +1 @@ +--- diff --git a/ansible/roles/opendaylight/tasks/config.yml b/ansible/roles/opendaylight/tasks/config.yml new file mode 100644 index 0000000000000000000000000000000000000000..06e49573375d47ddec0e8a3934741d7192a0b894 --- /dev/null +++ b/ansible/roles/opendaylight/tasks/config.yml @@ -0,0 +1,178 @@ +--- +- name: Setting sysctl values + sysctl: name={{ item.name }} value={{ item.value }} sysctl_set=yes + with_items: + - { name: "net.bridge.bridge-nf-call-iptables", value: 1} + - { name: "net.bridge.bridge-nf-call-ip6tables", value: 1} + - { name: "net.ipv4.conf.all.rp_filter", value: 0} + - { name: "net.ipv4.conf.default.rp_filter", value: 0} + when: + - set_sysctl | bool + - inventory_hostname in groups['opendaylight'] + +- name: Ensuring config directories exist + file: + path: "{{ node_config_directory }}/{{ item }}" + state: "directory" + recurse: yes + with_items: + - "opendaylight" + +- name: Copying over config.json files for services + register: opendaylight_config_json + template: + src: "{{ item }}.json.j2" + dest: "{{ node_config_directory }}/{{ item }}/config.json" + with_items: + - "opendaylight" + notify: + - Restart opendaylight container + +- name: Copying over custom.properties + register: opendaylight_config_custom_props + template: + src: "{{ role_path }}/templates/custom.properties.j2" + dest: "{{ node_config_directory }}/opendaylight/custom.properties" + notify: + - Restart opendaylight container + +- name: Copying over start-odl + register: opendaylight_config_start_odl + template: + src: "{{ role_path }}/templates/start-odl.j2" + dest: "{{ node_config_directory }}/opendaylight/start-odl" + notify: + - Restart opendaylight container + +- name: Copying over jetty.xml + register: opendaylight_config_jetty + template: + src: "{{ role_path }}/templates/jetty.xml.j2" + dest: "{{ node_config_directory }}/{{ item }}/jetty.xml" + with_items: + - "opendaylight" + notify: + - Restart opendaylight container + +- name: Copying over org.apache.karaf.features.cfg + register: opendaylight_config_features + template: + src: "{{ role_path }}/templates/org.apache.karaf.features.cfg.j2" + dest: "{{ node_config_directory }}/{{ item }}/org.apache.karaf.features.cfg" + with_items: + - "opendaylight" + notify: + - Restart opendaylight container + +- name: Copying over org.opendaylight.ovsdb.library.cfg + register: opendaylight_config_ovsdb + template: + src: "{{ role_path }}/templates/org.opendaylight.ovsdb.library.cfg.j2" + dest: "{{ node_config_directory }}/{{ item }}/org.opendaylight.ovsdb.library.cfg" + with_items: + - "opendaylight" + notify: + - Restart opendaylight container + +- name: Copying over tomcat-server.xml + template: + src: "{{ role_path }}/templates/tomcat-server.xml.j2" + dest: "{{ node_config_directory }}/{{ item }}/tomcat-server.xml" + register: opendaylight_config_tomcat + with_items: + - "opendaylight" + notify: + - Restart opendaylight container + +- name: Copying over org.ops4j.pax.logging.cfg.j2 + template: + src: "{{ role_path }}/templates/org.ops4j.pax.logging.cfg.j2" + dest: "{{ node_config_directory }}/{{ item }}/org.ops4j.pax.logging.cfg" + register: opendaylight_config_logging + with_items: + - "opendaylight" + notify: + - Restart opendaylight container + +- name: Copying over netvirt-impl-config_netvirt-impl-config.xml + template: + src: "{{ role_path }}/templates/netvirt-impl-config_netvirt-impl-config.xml.j2" + dest: "{{ node_config_directory }}/{{ item }}/netvirt-impl-config_netvirt-impl-config.xml" + register: opendaylight_config_netvirt + with_items: + - "opendaylight" + notify: + - Restart opendaylight container + +- name: Copying over netvirt-aclservice-config.xml + template: + src: "{{ role_path }}/templates/netvirt-aclservice-config.xml.j2" + dest: "{{ node_config_directory }}/{{ item }}/netvirt-aclservice-config.xml" + register: opendaylight_config_netvirt_acl + with_items: + - "opendaylight" + notify: + - Restart opendaylight container + +- name: Copying over setenv + template: + src: "{{ role_path }}/templates/setenv.j2" + dest: "{{ node_config_directory }}/{{ item }}/setenv" + register: opendaylight_config_env + with_items: + - "opendaylight" + notify: + - Restart opendaylight container + +- name: Copying over akka.conf + template: + src: "{{ role_path }}/templates/akka.conf.j2" + dest: "{{ node_config_directory }}/opendaylight/akka.conf" + with_first_found: + - "{{ node_custom_config }}/opendaylight/{{ inventory_hostname }}/akka.conf" + - "{{ node_custom_config }}/opendaylight/akka.conf" + - "akka.conf.j2" + register: opendaylight_config_akka + notify: + - Restart opendaylight container + +- name: Copying over modules.conf + template: + src: "{{ role_path }}/templates/modules.conf.j2" + dest: "{{ node_config_directory }}/opendaylight/modules.conf" + with_first_found: + - "{{ node_custom_config }}/opendaylight/{{ inventory_hostname }}/modules.conf" + - "{{ node_custom_config }}/opendaylight/modules.conf" + - "modules.conf.j2" + register: opendaylight_config_modules + notify: + - Restart opendaylight container + +- name: Copying over module-shards.conf + template: + src: "{{ role_path }}/templates/module-shards.conf.j2" + dest: "{{ node_config_directory }}/opendaylight/module-shards.conf" + with_first_found: + - "{{ node_custom_config }}/opendaylight/{{ inventory_hostname }}/module-shards.conf" + - "{{ node_custom_config }}/opendaylight/module-shards.conf" + - "module-shards.conf.j2" + register: opendaylight_config_module_shards + notify: + - Restart opendaylight container + +- name: Check opendaylight containers + kolla_docker: + action: "compare_container" + common_options: "{{ docker_common_options }}" + name: "{{ item.value.container_name }}" + image: "{{ item.value.image }}" + privileged: "{{ item.value.privileged | default(False) }}" + volumes: "{{ item.value.volumes }}" + register: check_opendaylight_containers + when: + - action != "config" + - item.value.enabled | bool + - item.value.host_in_groups | bool + with_dict: "{{ opendaylight_services }}" + notify: + - "Restart {{ item.key }} container" diff --git a/ansible/roles/opendaylight/tasks/deploy.yml b/ansible/roles/opendaylight/tasks/deploy.yml new file mode 100644 index 0000000000000000000000000000000000000000..5aac9f5a7f854e831b74bae654cce2a9b0dd2861 --- /dev/null +++ b/ansible/roles/opendaylight/tasks/deploy.yml @@ -0,0 +1,5 @@ +--- +- include: config.yml + +- name: Flush Handlers + meta: flush_handlers diff --git a/ansible/roles/opendaylight/tasks/main.yml b/ansible/roles/opendaylight/tasks/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..b017e8b4ad9edbc10e43b690b269d460e5b9b1f4 --- /dev/null +++ b/ansible/roles/opendaylight/tasks/main.yml @@ -0,0 +1,2 @@ +--- +- include: "{{ action }}.yml" diff --git a/ansible/roles/opendaylight/tasks/precheck.yml b/ansible/roles/opendaylight/tasks/precheck.yml new file mode 100644 index 0000000000000000000000000000000000000000..260e774f4ee7cdb490b54def0b848575b99e8d82 --- /dev/null +++ b/ansible/roles/opendaylight/tasks/precheck.yml @@ -0,0 +1,111 @@ +--- +- name: Get container facts + kolla_container_facts: + name: + - opendaylight + register: container_facts + +- name: Checking free port for opendaylight_clustering + wait_for: + host: "{{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}" + port: "{{ opendaylight_clustering_port }}" + connect_timeout: 1 + state: stopped + when: + - inventory_hostname in groups['opendaylight'] + - container_facts['opendaylight'] is not defined + +- name: Checking free port for opendaylight_restconf + wait_for: + host: "{{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}" + port: "{{ opendaylight_restconf_port }}" + connect_timeout: 1 + state: stopped + when: + - inventory_hostname in groups['opendaylight'] + - container_facts['opendaylight'] is not defined + +- name: Checking free port for opendaylight_restconf_backup + wait_for: + host: "{{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}" + port: "{{ opendaylight_restconf_port_backup }}" + connect_timeout: 1 + state: stopped + when: + - inventory_hostname in groups['opendaylight'] + - container_facts['opendaylight'] is not defined + +- name: Checking free port for opendaylight_karaf_ssh + wait_for: + host: "{{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}" + port: "{{ opendaylight_karaf_ssh_port }}" + connect_timeout: 1 + state: stopped + when: + - inventory_hostname in groups['opendaylight'] + - container_facts['opendaylight'] is not defined + +- name: Checking free port for opendaylight_openflow + wait_for: + host: "{{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}" + port: "{{ opendaylight_openflow_port }}" + connect_timeout: 1 + state: stopped + when: + - inventory_hostname in groups['opendaylight'] + - container_facts['opendaylight'] is not defined + +- name: Checking free port for opendaylight_ovsdb + wait_for: + host: "{{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}" + port: "{{ opendaylight_ovsdb_port }}" + connect_timeout: 1 + state: stopped + when: + - inventory_hostname in groups['opendaylight'] + - container_facts['opendaylight'] is not defined + +- name: Checking free port for opendaylight_jetty_conf_port + wait_for: + host: "{{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}" + port: "{{ opendaylight_jetty_conf_port }}" + connect_timeout: 1 + state: stopped + when: + - inventory_hostname in groups['opendaylight'] + - container_facts['opendaylight'] is not defined + +- name: Checking free port for opendaylight_jetty_conf2_port + wait_for: + host: "{{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}" + port: "{{ opendaylight_jetty_conf2_port }}" + connect_timeout: 1 + state: stopped + when: + - inventory_hostname in groups['opendaylight'] + - container_facts['opendaylight'] is not defined + +- name: Checking free port for opendaylight_tomcat_port + wait_for: + host: "{{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}" + port: "{{ opendaylight_tomcat_port }}" + connect_timeout: 1 + state: stopped + when: + - inventory_hostname in groups['opendaylight'] + - container_facts['opendaylight'] is not defined + +- name: Checking free port for opendaylight_tomcat_redirect_port + wait_for: + host: "{{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}" + port: "{{ opendaylight_tomcat_redirect_port }}" + connect_timeout: 1 + state: stopped + when: + - inventory_hostname in groups['opendaylight'] + - container_facts['opendaylight'] is not defined + +- name: Checking available opendaylight nodes in inventory + fail: + msg: "Either 1 or 3 nodes required in inventory for OpenDaylight clustering" + when: groups['opendaylight'] | length == 2 diff --git a/ansible/roles/opendaylight/tasks/pull.yml b/ansible/roles/opendaylight/tasks/pull.yml new file mode 100644 index 0000000000000000000000000000000000000000..76a1bd6b6a8e24b7972baa353caed47c7c58b2d3 --- /dev/null +++ b/ansible/roles/opendaylight/tasks/pull.yml @@ -0,0 +1,10 @@ +--- +- name: Pulling opendaylight image + kolla_docker: + action: "pull_image" + common_options: "{{ docker_common_options }}" + image: "{{ item.value.image }}" + when: + - item.value.enabled | bool + - item.value.host_in_groups | bool + with_dict: "{{ opendaylight_services }}" diff --git a/ansible/roles/opendaylight/tasks/reconfigure.yml b/ansible/roles/opendaylight/tasks/reconfigure.yml new file mode 100644 index 0000000000000000000000000000000000000000..e078ef1318f52fd9e74ccb13343015761312ca52 --- /dev/null +++ b/ansible/roles/opendaylight/tasks/reconfigure.yml @@ -0,0 +1,2 @@ +--- +- include: deploy.yml diff --git a/ansible/roles/opendaylight/tasks/upgrade.yml b/ansible/roles/opendaylight/tasks/upgrade.yml new file mode 100644 index 0000000000000000000000000000000000000000..5aac9f5a7f854e831b74bae654cce2a9b0dd2861 --- /dev/null +++ b/ansible/roles/opendaylight/tasks/upgrade.yml @@ -0,0 +1,5 @@ +--- +- include: config.yml + +- name: Flush Handlers + meta: flush_handlers diff --git a/ansible/roles/opendaylight/templates/akka.conf.j2 b/ansible/roles/opendaylight/templates/akka.conf.j2 new file mode 100644 index 0000000000000000000000000000000000000000..22d63e566fdd6ece7e62fb8f2f99754cde238eec --- /dev/null +++ b/ansible/roles/opendaylight/templates/akka.conf.j2 @@ -0,0 +1,33 @@ + +odl-cluster-data { + akka { + remote { + artery { + enabled = off + canonical.hostname = "{{ hostvars[inventory_hostname]['ansible_' + hostvars[inventory_hostname]['api_interface']]['ipv4']['address'] }}" + canonical.port = {{ opendaylight_clustering_port }} + } + netty.tcp { + hostname = "{{ hostvars[inventory_hostname]['ansible_' + hostvars[inventory_hostname]['api_interface']]['ipv4']['address'] }}" + port = {{ opendaylight_clustering_port }} + } + } + + cluster { + seed-nodes = [{% for host in groups['opendaylight'] %}"akka.tcp://opendaylight-cluster-data@{{ hostvars[host]['ansible_' + hostvars[host]['api_interface']]['ipv4']['address'] }}:{{ opendaylight_clustering_port }}"{% if not loop.last %},{% endif %}{% endfor %}] + + roles = [ + "{{ hostvars[inventory_hostname]['ansible_hostname'] }}" + ] + + } + + persistence { + + journal { + leveldb { + } + } + } + } +} diff --git a/ansible/roles/opendaylight/templates/custom.properties.j2 b/ansible/roles/opendaylight/templates/custom.properties.j2 new file mode 100644 index 0000000000000000000000000000000000000000..5f8c90cfeaff619c128559f5d0f40f0e1339cdee --- /dev/null +++ b/ansible/roles/opendaylight/templates/custom.properties.j2 @@ -0,0 +1,47 @@ +org.osgi.framework.system.packages.extra=org.apache.karaf.branding,sun.reflect,sun.reflect.misc,sun.misc,sun.nio.ch,com.sun.media.sound + +osgi.hook.configurators.include=org.eclipse.virgo.kernel.equinox.extensions.hooks.ExtensionsHookConfigurator + + +org.eclipse.gemini.web.tomcat.config.path=configuration/tomcat-server.xml +org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true + +karaf.framework=equinox + +karaf.delay.console=true + +org.apache.karaf.security.providers = org.bouncycastle.jce.provider.BouncyCastleProvider + +org.apache.aries.blueprint.preemptiveShutdown=false + +netconf.config.persister.active=1 + +netconf.config.persister.1.storageAdapterClass=org.opendaylight.controller.config.persist.storage.file.xml.XmlFileStorageAdapter +netconf.config.persister.1.properties.fileStorage=etc/opendaylight/current/controller.currentconfig.xml +netconf.config.persister.1.properties.numberOfBackups=1 + +logback.configurationFile=configuration/logback.xml + +container.profile = Container + +connection.scheme = ANY_CONTROLLER_ONE_MASTER + +ovsdb.l3.arp.responder.disabled=no + +secureChannelEnabled=false +controllerKeyStore= +controllerKeyStorePassword= +controllerTrustStore= +controllerTrustStorePassword= + +enableStrongPasswordCheck = false + +java.util.logging.config.file=configuration/tomcat-logging.properties + +hosttracker.keyscheme=IP + +lisp.mappingMerge = false + +lisp.smr = true + +lisp.elpPolicy = default diff --git a/ansible/roles/opendaylight/templates/jetty.xml.j2 b/ansible/roles/opendaylight/templates/jetty.xml.j2 new file mode 100644 index 0000000000000000000000000000000000000000..4e4cf897ca3e54cc9f4163d2b136d244d0d3677e --- /dev/null +++ b/ansible/roles/opendaylight/templates/jetty.xml.j2 @@ -0,0 +1,90 @@ +<?xml version="1.0"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting// +DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd"> + +<Configure class="org.eclipse.jetty.server.Server"> + <Call name="addConnector"> + <Arg> + <New class="org.eclipse.jetty.server.nio.SelectChannelConnector"> + <Set name="host"> + <Property name="jetty.host" /> + </Set> + <Set name="port"> + <Property name="jetty.port" default="{{ opendaylight_restconf_port }}" /> + </Set> + <Set name="maxIdleTime">300000</Set> + <Set name="Acceptors">2</Set> + <Set name="statsOn">false</Set> + <Set name="confidentialPort">{{ opendaylight_jetty_conf_port }}</Set> + <Set name="lowResourcesConnections">20000</Set> + <Set name="lowResourcesMaxIdleTime">5000</Set> + </New> + </Arg> + </Call> + <Call name="addConnector"> + <Arg> + <New class="org.eclipse.jetty.server.nio.SelectChannelConnector"> + <Set name="host"> + <Property name="jetty.host" /> + </Set> + <Set name="port"> + <Property name="jetty.port" default="{{ opendaylight_restconf_port_backup }}" /> + </Set> + <Set name="maxIdleTime">300000</Set> + <Set name="Acceptors">2</Set> + <Set name="statsOn">false</Set> + <Set name="confidentialPort">{{ opendaylight_jetty_conf2_port }}</Set> + <Set name="lowResourcesConnections">20000</Set> + <Set name="lowResourcesMaxIdleTime">5000</Set> + </New> + </Arg> + </Call> + + <Call name="addBean"> + <Arg> + <New class="org.eclipse.jetty.plus.jaas.JAASLoginService"> + <Set name="name">karaf</Set> + <Set name="loginModuleName">karaf</Set> + <Set name="roleClassNames"> + <Array type="java.lang.String"> + <Item>org.apache.karaf.jaas.boot.principal.RolePrincipal + </Item> + </Array> + </Set> + </New> + </Arg> + </Call> + <Call name="addBean"> + <Arg> + <New class="org.eclipse.jetty.plus.jaas.JAASLoginService"> + <Set name="name">default</Set> + <Set name="loginModuleName">karaf</Set> + <Set name="roleClassNames"> + <Array type="java.lang.String"> + <Item>org.apache.karaf.jaas.boot.principal.RolePrincipal + </Item> + </Array> + </Set> + </New> + </Arg> + </Call> + +</Configure> diff --git a/ansible/roles/opendaylight/templates/module-shards.conf.j2 b/ansible/roles/opendaylight/templates/module-shards.conf.j2 new file mode 100644 index 0000000000000000000000000000000000000000..4fe1f999ff8089697edc19acf893ad2a38281bc0 --- /dev/null +++ b/ansible/roles/opendaylight/templates/module-shards.conf.j2 @@ -0,0 +1,59 @@ +module-shards = [ + { + name = "default" + shards = [ + { + name="default" + replicas = [ + {% for host in groups['opendaylight'] %} + "{{ hostvars[host]['ansible_hostname'] }}"{% if not loop.last %}, + {% endif %} + {% endfor %} + ] + } + ] + }, + { + name = "topology" + shards = [ + { + name="topology" + replicas = [ + {% for host in groups['opendaylight'] %} + "{{ hostvars[host]['ansible_hostname'] }}"{% if not loop.last %}, + {% endif %} + {% endfor %} + ] + } + ] + }, + { + name = "inventory" + shards = [ + { + name="inventory" + replicas = [ + {% for host in groups['opendaylight'] %} + "{{ hostvars[host]['ansible_hostname'] }}"{% if not loop.last %}, + {% endif %} + {% endfor %} + ] + } + ] + }, + { + name = "toaster" + shards = [ + { + name="toaster" + replicas = [ + {% for host in groups['opendaylight'] %} + "{{ hostvars[host]['ansible_hostname'] }}"{% if not loop.last %}, + {% endif %} + {% endfor %} + ] + } + ] + } + +] diff --git a/ansible/roles/opendaylight/templates/modules.conf.j2 b/ansible/roles/opendaylight/templates/modules.conf.j2 new file mode 100644 index 0000000000000000000000000000000000000000..5b0711ea50cbae355536a363e41c49fa0df02d6e --- /dev/null +++ b/ansible/roles/opendaylight/templates/modules.conf.j2 @@ -0,0 +1,20 @@ +modules = [ + { + name = "inventory" + namespace = "urn:opendaylight:inventory" + shard-strategy = "module" + }, + + { + name = "topology" + namespace = "urn:TBD:params:xml:ns:yang:network-topology" + shard-strategy = "module" + }, + + { + name = "toaster" + namespace = "http://netconfcentral.org/ns/toaster" + shard-strategy = "module" + } + +] diff --git a/ansible/roles/opendaylight/templates/netvirt-aclservice-config.xml.j2 b/ansible/roles/opendaylight/templates/netvirt-aclservice-config.xml.j2 new file mode 100644 index 0000000000000000000000000000000000000000..398719570bc13f10f8b3b56669669dbc319d467b --- /dev/null +++ b/ansible/roles/opendaylight/templates/netvirt-aclservice-config.xml.j2 @@ -0,0 +1,4 @@ +<aclservice-config xmlns="urn:opendaylight:netvirt:aclservice-config"> + <security-group-mode>{{ opendaylight_acl_impl }}</security-group-mode> + <default-behavior>deny</default-behavior> +</aclservice-config> diff --git a/ansible/roles/opendaylight/templates/netvirt-impl-config_netvirt-impl-config.xml.j2 b/ansible/roles/opendaylight/templates/netvirt-impl-config_netvirt-impl-config.xml.j2 new file mode 100644 index 0000000000000000000000000000000000000000..9e22e427a34e26b9097adb9bab44c7cb603c6bc3 --- /dev/null +++ b/ansible/roles/opendaylight/templates/netvirt-impl-config_netvirt-impl-config.xml.j2 @@ -0,0 +1,7 @@ +{% if enable_opendaylight_legacy_netvirt_conntrack | bool %} +<netvirt-impl-config xmlns="urn:opendaylight:params:xml:ns:yang:netvirt:impl:config"> + <conntrack-enabled> + true + </conntrack-enabled> +</netvirt-impl-config> +{% endif %} diff --git a/ansible/roles/opendaylight/templates/opendaylight.json.j2 b/ansible/roles/opendaylight/templates/opendaylight.json.j2 new file mode 100644 index 0000000000000000000000000000000000000000..e475b9cb15b84d24de65d68bd8bc7de85c7fb6ec --- /dev/null +++ b/ansible/roles/opendaylight/templates/opendaylight.json.j2 @@ -0,0 +1,90 @@ +{ + "command": "start-odl", + "config_files": [ + { + "source": "{{ container_config_directory }}/start-odl", + "dest": "/usr/local/bin/start-odl", + "owner": "odl", + "perm": "0655" + }, + { + "source": "{{ container_config_directory }}/org.apache.karaf.features.cfg", + "dest": "/opt/opendaylight/etc/org.apache.karaf.features.cfg", + "owner": "odl", + "perm": "0600" + }, + { + "source": "{{ container_config_directory }}/org.opendaylight.ovsdb.library.cfg", + "dest": "/opt/opendaylight/etc/org.opendaylight.ovsdb.library.cfg", + "owner": "odl", + "perm": "0600" + }, + { + "source": "{{ container_config_directory }}/tomcat-server.xml", + "dest": "/opt/opendaylight/configuration/tomcat-server.xml", + "owner": "odl", + "perm": "0600" + }, + { + "source": "{{ container_config_directory }}/jetty.xml", + "dest": "/opt/opendaylight/etc/jetty.xml", + "owner": "odl", + "perm": "0600" + }, + { + "source": "{{ container_config_directory }}/org.ops4j.pax.logging.cfg", + "dest": "/opt/opendaylight/etc/org.ops4j.pax.logging.cfg", + "owner": "odl", + "perm": "0600" + }, + { + "source": "/var/lib/kolla/config_files/custom.properties", + "dest": "/opt/opendaylight/etc/custom.properties", + "owner": "odl", + "perm": "0600" + }, + { + "source": "{{ container_config_directory }}/netvirt-impl-config_netvirt-impl-config.xml", + "dest": "/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-impl-config_netvirt-impl-config.xml", + "owner": "odl", + "perm": "0600" + }, + { + "source": "{{ container_config_directory }}/netvirt-aclservice-config.xml", + "dest": "/opt/opendaylight/etc/opendaylight/datastore/initial/config/netvirt-aclservice-config.xml", + "owner": "odl", + "perm": "0600" + }, + { + "source": "{{ container_config_directory }}/setenv", + "dest": "/opt/opendaylight/bin/setenv", + "owner": "odl", + "perm": "0600" + }, + { + "source": "{{ container_config_directory }}/akka.conf", + "dest": "/opt/opendaylight/configuration/initial/akka.conf", + "owner": "odl", + "perm": "0600" + }, + { + "source": "{{ container_config_directory }}/modules.conf", + "dest": "/opt/opendaylight/configuration/initial/modules.conf", + "owner": "odl", + "perm": "0600" + }, + { + "source": "{{ container_config_directory }}/module-shards.conf", + "dest": "/opt/opendaylight/configuration/initial/module-shards.conf", + "owner": "odl", + "perm": "0600" + } + ], + "permissions": [ + { + "path": "/var/log/kolla/opendaylight", + "owner": "odl:odl", + "recurse": true + } + ] +} diff --git a/ansible/roles/opendaylight/templates/org.apache.karaf.features.cfg.j2 b/ansible/roles/opendaylight/templates/org.apache.karaf.features.cfg.j2 new file mode 100644 index 0000000000000000000000000000000000000000..ba2dfcd5133278bf67088cd30e2334405326983d --- /dev/null +++ b/ansible/roles/opendaylight/templates/org.apache.karaf.features.cfg.j2 @@ -0,0 +1,24 @@ +################################################################################ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +################################################################################ + +featuresRepositories = mvn:org.apache.karaf.features/standard/3.0.8/xml/features,mvn:org.apache.karaf.features/enterprise/3.0.8/xml/features,mvn:org.ops4j.pax.web/pax-web-features/3.2.9/xml/features,mvn:org.apache.karaf.features/spring/3.0.8/xml/features,mvn:org.opendaylight.integration/features-integration-index/{{ opendaylight_release }}/xml/features + +featuresBoot=config,standard,region,package,kar,ssh,management{% if not opendaylight_features == '' %},{% endif %}{{ opendaylight_features }} + +featuresBootAsynchronous=false diff --git a/ansible/roles/opendaylight/templates/org.opendaylight.ovsdb.library.cfg.j2 b/ansible/roles/opendaylight/templates/org.opendaylight.ovsdb.library.cfg.j2 new file mode 100644 index 0000000000000000000000000000000000000000..d5cae1b52fbfed510f3f7d330fd3207a1cfb0321 --- /dev/null +++ b/ansible/roles/opendaylight/templates/org.opendaylight.ovsdb.library.cfg.j2 @@ -0,0 +1,7 @@ +ovsdb-listener-port = {{ opendaylight_ovsdb_port }} + +use-ssl = false + +json-rpc-decoder-max-frame-length = 100000 + +ovsdb-rpc-task-timeout = 1000 diff --git a/ansible/roles/opendaylight/templates/org.ops4j.pax.logging.cfg.j2 b/ansible/roles/opendaylight/templates/org.ops4j.pax.logging.cfg.j2 new file mode 100644 index 0000000000000000000000000000000000000000..d2aa291f4b388946d1c577cefb8cd03126511e77 --- /dev/null +++ b/ansible/roles/opendaylight/templates/org.ops4j.pax.logging.cfg.j2 @@ -0,0 +1,52 @@ +################################################################################ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +################################################################################ + +log4j.rootLogger=INFO, async, osgi:* +log4j.throwableRenderer=org.apache.log4j.OsgiThrowableRenderer + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n + +log4j.appender.async=org.apache.log4j.AsyncAppender +log4j.appender.async.appenders=out + +log4j.appender.out=org.apache.log4j.RollingFileAppender +log4j.appender.out.layout=org.apache.log4j.PatternLayout +log4j.appender.out.layout.ConversionPattern=%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n +log4j.appender.out.file=/var/log/kolla/opendaylight/karaf.log +log4j.appender.out.append=true +log4j.appender.out.maxFileSize=1MB +log4j.appender.out.maxBackupIndex=10 + +log4j.appender.sift=org.apache.log4j.sift.MDCSiftingAppender +log4j.appender.sift.key=bundle.name +log4j.appender.sift.default=karaf +log4j.appender.sift.appender=org.apache.log4j.FileAppender +log4j.appender.sift.appender.layout=org.apache.log4j.PatternLayout +log4j.appender.sift.appender.layout.ConversionPattern=%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %m%n +log4j.appender.sift.appender.file=/var/log/kolla/opendaylight/$\\{bundle.name\\}.log +log4j.appender.sift.appender.append=true + +log4j.appender.syslog=org.apache.log4j.net.SyslogAppender +log4j.appender.syslog.layout=org.apache.log4j.PatternLayout +log4j.appender.syslog.layout.ConversionPattern=%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n +log4j.appender.syslog.syslogHost=127.0.0.1 +log4J.appender.syslog.facility=KARAF +log4j.appender.syslog.facilityPrinting=false diff --git a/ansible/roles/opendaylight/templates/org.ops4j.pax.url.mvn.cfg.j2 b/ansible/roles/opendaylight/templates/org.ops4j.pax.url.mvn.cfg.j2 new file mode 100644 index 0000000000000000000000000000000000000000..37e9e24206d831f95988398529cb17e6dbc71a17 --- /dev/null +++ b/ansible/roles/opendaylight/templates/org.ops4j.pax.url.mvn.cfg.j2 @@ -0,0 +1,34 @@ +################################################################################ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +################################################################################ + +org.ops4j.pax.url.mvn.settings=/var/lib/odl/.m2/settings.xml + +org.ops4j.pax.url.mvn.localRepository=${karaf.home}/${karaf.default.repository} + +org.ops4j.pax.url.mvn.useFallbackRepositories=false + +org.ops4j.pax.url.mvn.defaultLocalRepoAsRemote=false + +org.ops4j.pax.url.mvn.repositories= \ +file:${karaf.home}/${karaf.default.repository}@id=system.repository, \ +file:${karaf.data}/kar@id=kar.repository@multi, \ +http://repo1.maven.org/maven2@id=central, \ +http://repository.springsource.com/maven/bundles/release@id=spring.ebr.release, \ +http://repository.springsource.com/maven/bundles/external@id=spring.ebr.external, \ +http://zodiac.springsource.com/maven/bundles/release@id=gemini diff --git a/ansible/roles/opendaylight/templates/setenv.j2 b/ansible/roles/opendaylight/templates/setenv.j2 new file mode 100644 index 0000000000000000000000000000000000000000..7376186e1836e894dfb3a8bc22b1e3860ab74f85 --- /dev/null +++ b/ansible/roles/opendaylight/templates/setenv.j2 @@ -0,0 +1,24 @@ +#!/bin/sh +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if [ "x$JAVA_MAX_PERM_MEM" = "x" ]; then + export JAVA_MAX_PERM_MEM="512m" +fi +if [ "x$JAVA_MAX_MEM" = "x" ]; then + export JAVA_MAX_MEM="8g" +fi diff --git a/ansible/roles/opendaylight/templates/start-odl.j2 b/ansible/roles/opendaylight/templates/start-odl.j2 new file mode 100644 index 0000000000000000000000000000000000000000..e039b1c65566cd622ca47cdbc312666dbb317c96 --- /dev/null +++ b/ansible/roles/opendaylight/templates/start-odl.j2 @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +java -jar /opt/opendaylight/bin/aaa-cli-jar.jar --dbd /opt/opendaylight/ --nu admin -p {{ opendaylight_password }} +/opt/opendaylight/bin/karaf diff --git a/ansible/roles/opendaylight/templates/tomcat-server.xml.j2 b/ansible/roles/opendaylight/templates/tomcat-server.xml.j2 new file mode 100644 index 0000000000000000000000000000000000000000..1d199d591ebe82daa05124fa9bedf5dd199eaf64 --- /dev/null +++ b/ansible/roles/opendaylight/templates/tomcat-server.xml.j2 @@ -0,0 +1,46 @@ +<?xml version='1.0' encoding='utf-8'?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<Server> + <!--APR library loader. Documentation at /docs/apr.html --> + <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /> + <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html --> + <Listener className="org.apache.catalina.core.JasperListener" /> + <!-- Prevent memory leaks due to use of particular java/javax APIs--> + <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /> + <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> + <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" /> + + <Service name="Catalina"> + <Connector port="{{ opendaylight_tomcat_port }}" protocol="HTTP/1.1" + connectionTimeout="20000" + redirectPort="{{ opendaylight_tomcat_redirect_port }}" /> + + <Engine name="Catalina" defaultHost="localhost"> + <Host name="localhost" appBase="" + unpackWARs="false" autoDeploy="false" + deployOnStartup="false" createDirs="false"> + <Realm className="org.opendaylight.controller.karafsecurity.ControllerCustomRealm" /> + <Valve className="org.apache.catalina.authenticator.SingleSignOn" /> + <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" + prefix="web_access_log_" suffix=".txt" resolveHosts="false" + rotatable="true" fileDateFormat="yyyy-MM" + pattern="%{yyyy-MM-dd HH:mm:ss.SSS z}t - [%a] - %r"/> + </Host> + </Engine> + </Service> +</Server> diff --git a/ansible/roles/openvswitch/handlers/main.yml b/ansible/roles/openvswitch/handlers/main.yml index 155536d836120ca38df3cb75cde23cfbdd655f03..d631076ea1d370cb681d193d36be8b319bd54714 100644 --- a/ansible/roles/openvswitch/handlers/main.yml +++ b/ansible/roles/openvswitch/handlers/main.yml @@ -17,6 +17,8 @@ - service.host_in_groups | bool - config_json | changed or openvswitch_db_container | changed + or openvswitch_start_ovsdb_server | changed + notify: - Waiting for openvswitch_db service to be ready - Ensuring OVS bridge is properly setup @@ -60,3 +62,4 @@ - service.host_in_groups | bool - config_json | changed or openvswitch_vswitchd_container | changed + or openvswitch_start_ovs | changed diff --git a/ansible/roles/openvswitch/tasks/config.yml b/ansible/roles/openvswitch/tasks/config.yml index 0a24c63f4fa517103b6bc6f8ff13914d87a1f2b9..fb5dff238108c045e2494a8d55f7565bf56ae353 100644 --- a/ansible/roles/openvswitch/tasks/config.yml +++ b/ansible/roles/openvswitch/tasks/config.yml @@ -21,6 +21,32 @@ notify: - "Restart {{ item.key }} container" +- name: Copying over start-ovs file for openvswitch-vswitchd + vars: + service: "{{ openvswitch_services['openvswitch-vswitchd'] }}" + template: + src: "{{ role_path }}/templates/start-ovs.j2" + dest: "{{ node_config_directory }}/openvswitch-vswitchd/start-ovs" + register: openvswitch_start_ovs + when: + - inventory_hostname in groups[service.group] + - service.enabled | bool + notify: + - "Restart openvswitch-vswitchd container" + +- name: Copying over start-ovsdb-server files for openvswitch-db-server + vars: + service: "{{ openvswitch_services['openvswitch-db-server'] }}" + template: + src: "{{ role_path }}/templates/start-ovsdb-server.j2" + dest: "{{ node_config_directory }}/openvswitch-db-server/start-ovsdb-server" + register: openvswitch_start_ovsdb_server + when: + - inventory_hostname in groups[service.group] + - service.enabled | bool + notify: + - "Restart openvswitch-db-server container" + - name: Check openvswitch containers kolla_docker: action: "compare_container" diff --git a/ansible/roles/openvswitch/templates/openvswitch-db-server.json.j2 b/ansible/roles/openvswitch/templates/openvswitch-db-server.json.j2 index fdeea72ecbc3cdc1bcd1b4236f7a4bb17c8265b9..955131cf81a60a44eecbcd0616d6c17c094b74f9 100644 --- a/ansible/roles/openvswitch/templates/openvswitch-db-server.json.j2 +++ b/ansible/roles/openvswitch/templates/openvswitch-db-server.json.j2 @@ -1,4 +1,11 @@ { "command": "start-ovsdb-server {{ api_interface_address }}", - "config_files": [] + "config_files": [ + { + "source": "{{ container_config_directory }}/start-ovsdb-server", + "dest": "/usr/local/bin/start-ovsdb-server", + "owner": "root", + "perm": "0655" + } + ] } diff --git a/ansible/roles/openvswitch/templates/openvswitch-vswitchd.json.j2 b/ansible/roles/openvswitch/templates/openvswitch-vswitchd.json.j2 index 97308d886bd424114549fdee64293442a197a319..0c75c355f621f143c2442d448bb2d7791f52155a 100644 --- a/ansible/roles/openvswitch/templates/openvswitch-vswitchd.json.j2 +++ b/ansible/roles/openvswitch/templates/openvswitch-vswitchd.json.j2 @@ -1,4 +1,11 @@ { - "command": "/usr/sbin/ovs-vswitchd unix:/run/openvswitch/db.sock -vconsole:emer -vsyslog:err -vfile:info --mlockall --log-file=/var/log/kolla/openvswitch/ovs-vswitchd.log", - "config_files": [] + "command": "start-ovs", + "config_files": [ + { + "source": "{{ container_config_directory }}/start-ovs", + "dest": "/usr/local/bin/start-ovs", + "owner": "root", + "perm": "0655" + } + ] } diff --git a/ansible/roles/openvswitch/templates/start-ovs.j2 b/ansible/roles/openvswitch/templates/start-ovs.j2 new file mode 100644 index 0000000000000000000000000000000000000000..d6dd723b688b5b08cca71d5983750212ef22ddda --- /dev/null +++ b/ansible/roles/openvswitch/templates/start-ovs.j2 @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +{% if enable_opendaylight | bool %} +/usr/bin/ovs-vsctl --no-wait -- set-manager ptcp:{{ ovsdb_port }}:{{ hostvars[inventory_hostname]['ansible_' + hostvars[inventory_hostname]['api_interface']]['ipv4']['address'] }} tcp:{{ kolla_internal_vip_address }}:{{ opendaylight_haproxy_ovsdb_port }} +/usr/bin/ovs-vsctl --no-wait -- set Open_vSwitch . other_config:local_ip={{ hostvars[inventory_hostname]['ansible_' + hostvars[inventory_hostname]['tunnel_interface']]['ipv4']['address'] }} +/usr/bin/ovs-vsctl --no-wait -- set Open_vSwitch . other_config:provider_mappings=physnet1:{{ neutron_bridge_name }} +/usr/bin/ovs-vsctl --no-wait -- set Open_vSwitch . external_ids:system-id=`cat /proc/sys/kernel/random/uuid` +/usr/bin/ovs-vsctl --no-wait -- set Open_vSwitch . external_ids:odl_os_hostconfig_config_odl_l2='{"supported_vnic_types": [{"vnic_type": "normal", "vif_type": "ovs", "vif_details": {} }], "allowed_network_types": [{{ opendaylight_allowed_network_types }}], "datapath_types": ["netdev", "system"], "bridge_mappings": {"physnet1":"{{ neutron_bridge_name }}"} }' +/usr/bin/ovs-vsctl --no-wait -- set Open_vSwitch . external_ids:odl_os_hostconfig_hostid="{{ hostvars[inventory_hostname]['ansible_hostname'] }}" +{% endif %} +/usr/sbin/ovs-vswitchd unix:/run/openvswitch/db.sock -vconsole:emer -vsyslog:err -vfile:info --mlockall --log-file=/var/log/kolla/openvswitch/ovs-vswitchd.log diff --git a/ansible/roles/openvswitch/templates/start-ovsdb-server.j2 b/ansible/roles/openvswitch/templates/start-ovsdb-server.j2 new file mode 100644 index 0000000000000000000000000000000000000000..803e85660e4314722da9c9d66f5f30635a3b9cab --- /dev/null +++ b/ansible/roles/openvswitch/templates/start-ovsdb-server.j2 @@ -0,0 +1,33 @@ +#!/bin/bash + +# NOTE: (sbezverk) ovs_bridge and ovs_ext_intf variables get initialized only when +# this script is executed for kubernetes deployment. With Ansible deployment, only +# ovsdb-server gets launched and then the following workflow step will create +# an external bridge and plug an external interface. With Kubernetes we want to +# leverage its dynamic nature of automatic scaling up and down. It means all +# activities related to creating initial bridge, plugging external interface +# must be done by DaemonSet launched container. + +ovsdb_ip=$1 +ovs_bridge=$2 +ovs_ext_intf=$3 + +printf "Argument p_out is %s\n" "$p_out" +printf "Argument arg_1 is %s\n" "$arg_1" + +# NOTE: (sbezverk) The reason for introducing this script is to be able +# to launch ovsdb-server and to create the initial external bridge in one step. +# It is required in order to be able to use DaemonSet. + +if [ ! -e $ovs_bridge ] && [ ! -e $ovs_ext_intf ]; then +# NOTE: (sbezverk) This part is executed only by kubernetes deployment. +# Creating external bridge + /usr/sbin/ovsdb-server /var/lib/openvswitch/conf.db --remote=punix:/var/run/openvswitch/db.sock --run="ovs-vsctl --no-wait --db=unix:/var/run/openvswitch/db.sock add-br $ovs_bridge" +# Plug the external interface into the external bridge. + /usr/sbin/ovsdb-server /var/lib/openvswitch/conf.db --remote=punix:/var/run/openvswitch/db.sock --run="ovs-vsctl --no-wait --db=unix:/var/run/openvswitch/db.sock add-port $ovs_bridge $ovs_ext_intf" +# Run ovsdb server process + /usr/sbin/ovsdb-server /var/lib/openvswitch/conf.db -vconsole:emer -vsyslog:err -vfile:info --remote=punix:/var/run/openvswitch/db.sock --remote=ptcp:6640 --log-file=/var/log/kolla/openvswitch/ovsdb-server.log +else +# NOTE: (sbezverk) This part is executed only by kolla-ansible deployment. + /usr/sbin/ovsdb-server /var/lib/openvswitch/conf.db -vconsole:emer -vsyslog:err -vfile:info --remote=punix:/run/openvswitch/db.sock --remote=ptcp:{{ ovsdb_port }}:$ovsdb_ip --remote=db:Open_vSwitch,Open_vSwitch,manager_options --log-file=/var/log/kolla/openvswitch/ovsdb-server.log +fi diff --git a/ansible/site.yml b/ansible/site.yml index 0ed2edc28ced2ebe1b6e1826bf79d83a29b5437a..50cbce1fa04d4c15649dd35f55f3e0aa38cd2664 100644 --- a/ansible/site.yml +++ b/ansible/site.yml @@ -308,6 +308,14 @@ tags: nova, when: enable_nova | bool } +- name: Apply role opendaylight + gather_facts: false + hosts: opendaylight + roles: + - { role: opendaylight, + tags: opendaylight, + when: enable_opendaylight | bool } + - name: Apply role openvswitch hosts: - openvswitch diff --git a/etc/kolla/globals.yml b/etc/kolla/globals.yml index 5227f9da79c92d024b5cc091c822b6c419eccb6f..f0a4b659630fc6b90dc3cc72f03b3cb0065d8b9f 100644 --- a/etc/kolla/globals.yml +++ b/etc/kolla/globals.yml @@ -86,7 +86,7 @@ kolla_internal_vip_address: "10.10.10.254" # addresses for that reason. #neutron_external_interface: "eth1" -# Valid options are [ openvswitch, linuxbridge, vmware_nsxv, vmware_dvs ] +# Valid options are [ openvswitch, linuxbridge, vmware_nsxv, vmware_dvs, opendaylight ] #neutron_plugin_agent: "openvswitch" @@ -107,6 +107,12 @@ kolla_internal_vip_address: "10.10.10.254" #kolla_external_fqdn_cert: "{{ node_config_directory }}/certificates/haproxy.pem" +############################### +# OpenDaylight +############################### +#enable_opendaylight_qos: "no" +#enable_opendaylight_l3: "yes" + #################### # OpenStack options #################### @@ -184,6 +190,7 @@ kolla_internal_vip_address: "10.10.10.254" #enable_neutron_sfc: "no" #enable_nova_serialconsole_proxy: "no" #enable_octavia: "no" +#enable_opendaylight: "no" #enable_openvswitch: "{{ neutron_plugin_agent != 'linuxbridge' }}" #enable_osprofiler: "no" #enable_panko: "no" diff --git a/etc/kolla/passwords.yml b/etc/kolla/passwords.yml index 822c32e642b6b7acc009901b8ff04b73b116de97..b126c5a1314d6a555ad9764544989e0ae4cb7039 100644 --- a/etc/kolla/passwords.yml +++ b/etc/kolla/passwords.yml @@ -22,6 +22,11 @@ database_password: # This should only be set if you require a password for your Docker registry docker_registry_password: +###################### +# OpenDaylight options +###################### +opendaylight_password: + #################### # OpenStack options #################### diff --git a/releasenotes/notes/opendaylight-role-b1787bc458da5bc4.yaml b/releasenotes/notes/opendaylight-role-b1787bc458da5bc4.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b7c0ae0f89ee62bf094a35fc007c34440f5fe095 --- /dev/null +++ b/releasenotes/notes/opendaylight-role-b1787bc458da5bc4.yaml @@ -0,0 +1,3 @@ +--- +features: + - Add OpenDaylight role \ No newline at end of file