diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml
index ef6ccc7d6b..992eb4b2d9 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 154abf5e6f..f9c6de918b 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 8b57b3d4d1..c319219ce3 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 49c7e029d4..bdde3f92da 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 f24ab2b4aa..e52d60a692 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 71c40967cc..240482db44 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 054b8faa43..279423ba3a 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 076e9a5eae..9f83c71f9d 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 919c7422c6..d1aa1d8681 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 0000000000..f2d35bda47
--- /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 0000000000..0a5f9eec70
--- /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 0000000000..6b4fff8fef
--- /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 0000000000..ed97d539c0
--- /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 0000000000..06e4957337
--- /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 0000000000..5aac9f5a7f
--- /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 0000000000..b017e8b4ad
--- /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 0000000000..260e774f4e
--- /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 0000000000..76a1bd6b6a
--- /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 0000000000..e078ef1318
--- /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 0000000000..5aac9f5a7f
--- /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 0000000000..22d63e566f
--- /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 0000000000..5f8c90cfea
--- /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 0000000000..4e4cf897ca
--- /dev/null
+++ b/ansible/roles/opendaylight/templates/jetty.xml.j2
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 300000
+ 2
+ false
+ {{ opendaylight_jetty_conf_port }}
+ 20000
+ 5000
+
+
+
+
+
+
+
+
+
+
+
+
+ 300000
+ 2
+ false
+ {{ opendaylight_jetty_conf2_port }}
+ 20000
+ 5000
+
+
+
+
+
+
+
+ karaf
+ karaf
+
+
+ - org.apache.karaf.jaas.boot.principal.RolePrincipal
+
+
+
+
+
+
+
+
+
+ default
+ karaf
+
+
+ - org.apache.karaf.jaas.boot.principal.RolePrincipal
+
+
+
+
+
+
+
+
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 0000000000..4fe1f999ff
--- /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 0000000000..5b0711ea50
--- /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 0000000000..398719570b
--- /dev/null
+++ b/ansible/roles/opendaylight/templates/netvirt-aclservice-config.xml.j2
@@ -0,0 +1,4 @@
+
+ {{ opendaylight_acl_impl }}
+ deny
+
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 0000000000..9e22e427a3
--- /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 %}
+
+
+ true
+
+
+{% endif %}
diff --git a/ansible/roles/opendaylight/templates/opendaylight.json.j2 b/ansible/roles/opendaylight/templates/opendaylight.json.j2
new file mode 100644
index 0000000000..e475b9cb15
--- /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 0000000000..ba2dfcd513
--- /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 0000000000..d5cae1b52f
--- /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 0000000000..d2aa291f4b
--- /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 0000000000..37e9e24206
--- /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 0000000000..7376186e18
--- /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 0000000000..e039b1c655
--- /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 0000000000..1d199d591e
--- /dev/null
+++ b/ansible/roles/opendaylight/templates/tomcat-server.xml.j2
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ansible/roles/openvswitch/handlers/main.yml b/ansible/roles/openvswitch/handlers/main.yml
index 155536d836..d631076ea1 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 0a24c63f4f..fb5dff2381 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 fdeea72ecb..955131cf81 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 97308d886b..0c75c355f6 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 0000000000..d6dd723b68
--- /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 0000000000..803e85660e
--- /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 0ed2edc28c..50cbce1fa0 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 5227f9da79..f0a4b65963 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 822c32e642..b126c5a131 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 0000000000..b7c0ae0f89
--- /dev/null
+++ b/releasenotes/notes/opendaylight-role-b1787bc458da5bc4.yaml
@@ -0,0 +1,3 @@
+---
+features:
+ - Add OpenDaylight role
\ No newline at end of file