diff --git a/.gitignore b/.gitignore index 00efc26..0868483 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,27 @@ .build/ calico-fuel-plugin-*.rpm +*~ +*.swp +*.gem +*.rbc +.idea +.bundle +.config +*.lock +*.diff +coverage +InstalledFiles +lib/bundler/man +pkg +rdoc +spec/reports +spec/fixtures/modules +spec/fixtures/manifests +test/tmp +test/version_tmp +tmp + +# YARD artifacts +.yardoc +_yardoc +doc/ diff --git a/README.md b/README.md index 85fca1a..2ade030 100755 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ None. Compatible versions: -------------------- - Mirantis Fuel 7.0 + Mirantis Fuel 9.0 To build the plugin: -------------------- @@ -39,18 +39,15 @@ To build the plugin: - Install the fuel plugin builder, fpb: easy_install pip - pip install fuel-plugin-builder - Clone the calico plugin repository and run the plugin builder: git clone https://github.com/openstack/fuel-plugin-calico - cd fuel-plugin-calico/ - fpb --build . -- Check that the file calico-fuel-plugin-2.0-2.0.0-0.noarch.rpm was created. +- Check that the file fuel-plugin-calico-VERSION.noarch.rpm was created. To install the plugin: @@ -60,13 +57,16 @@ To install the plugin: - Copy the plugin onto the fuel master node: - scp calico-fuel-plugin-2.0-2.0.0-0.noarch.rpm root@:/tmp + scp fuel-plugin-calico-VERSION.noarch.rpm root@:/tmp + +- Install the `patch` utility: + + yum install -y patch - Install the plugin on the fuel master node: cd /tmp - - fuel plugins --install calico-fuel-plugin-2.0-2.0.0-0.noarch.rpm + fuel plugins --install fuel-plugin-calico-VERSION.noarch.rpm - Check the plugin was installed: @@ -81,27 +81,85 @@ OpenStack cluster in the usual way, with the following guidelines: - Create a new OpenStack environment, selecting: - Kilo on Ubuntu Trusty + Mitaka on Ubuntu 14.04 + "Calico networking" as the networking setup - "Neutron with VLAN segmentation" as the networking setup - -- Under the settings tab, make sure the following options are checked: - - "Assign public network to all nodes" - - "Use Calico Virtual Networking" - -- Under the network tab, configure the 'Public' settings (leaving all of the - other sections with their default values). For example (exact values will +- Under the network tab, configure the `Public` settings to reduce + Floating-IP addresses pool to one address, + because Calico does not support Floating IPs use-case. + For example (exact values will depend on your setup): - - IP Range: 172.18.203.60 - 172.18.203.69 - - CIDR: 172.18.203.0/24 - - Use VLAN tagging: No - - Gateway: 172.18.203.1 - - Floating IP range: 172.18.203.70 - 172.18.203.79 + Node Network Group + default: + CIDR: 172.18.203.0/24 + IP Range: 172.18.203.2 - 172.18.203.253 + Gateway: 172.18.203.1 + Use VLAN tagging: No + + Settings + Neutron L3: + Floating IP range: 172.18.203.254 - 172.18.203.254 + +- Under the network tab, configure the `Private` network settings + (this network will be used for BGP peering between custer nodes, route + reflectors and external peers, configured by UI). Do not forget to exclude + Your BGP peers and gateway from the IP range! + For example (exact values will depend on your setup): + + IP Range: 172.100.203.33 - 172.100.203.254 + CIDR: 172.100.203.0/24 + Use VLAN tagging: No + +- Under Fuel CLI, configure gateway for `Private` network. + This gateway will be used for pass outgoing external traffic from instances. + In most cases the same gateway node should be also an external BGB peer + (see below, external BGB peer-1). + + [root@nailgun ~]# fuel2 network-group list + +----+---------+------------+---------------+---------+----------+ + | id | name | vlan_start | cidr | gateway | group_id | + +----+---------+------------+---------------+---------+----------+ + | 5 | private | None | 10.88.12.0/24 | None | 1 | + +----+---------+------------+---------------+---------+----------+ + [root@nailgun ~]# fuel2 network-group update -g 10.88.12.1 5 + +------------+---------------+ + | Field | Value | + +------------+---------------+ + | id | 5 | + | name | private | + | vlan_start | None | + | cidr | 10.88.12.0/24 | + | gateway | 10.88.12.1 | + | group_id | 1 | + +------------+---------------+ + +- Under the network tab, configure IP pool for Calico network fabric. + Ip addresses from this pool will be assigned to VM instances: + + Settings + Neutron L3: + Admin Tenant network CIDR: 10.10.0.0/16 + Admin Tenant network gateway: 10.10.0.1 + +- Under the network tab, in the `other/Calico_networking` section setup + AS number, external BGP peering and another Calico networking options. + + AS Number: 64513 + + [X] Allow external BGP peering + External BGP peers: + peer-1:65000:10.88.12.1 + peer-2:65002:172.100.203.13 - Add nodes (for meaningful testing, you will need at least two compute nodes - in addition to the controller). + in addition to the controller). Calico-RR (route-reflector) and Calico-ETCD + node roles may be co-located on Controller nodes or deployed separately. + +- Under the nodes tab, configure networks to NICs mapping + (exact positions will depend on your setup) - Deploy changes + +- Do not forget to configure BGP peering session on you infrastructure + BGP peers. diff --git a/components.yaml b/components.yaml new file mode 100644 index 0000000..6dbe7d7 --- /dev/null +++ b/components.yaml @@ -0,0 +1,12 @@ +- name: 'network:neutron:calico' + label: 'Calico' + description: 'Calico networking' + bind: !!pairs + - "cluster:net_provider": "neutron" + - "cluster:net_segment_type": "tun" + compatible: + - name: 'hypervisor:kvm' + - name: 'hypervisor:qemu' + incompatible: + - name: 'hypervisor:vmware' + description: 'Calico plugin is not compatible with VMware for now' \ No newline at end of file diff --git a/deployment_scripts/calico-fuel-monitor b/deployment_scripts/calico-fuel-monitor deleted file mode 100755 index 19bd7ed..0000000 --- a/deployment_scripts/calico-fuel-monitor +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python - -import pyinotify -import subprocess -import yaml - -from pluginutils import NODES_CONFIG - -SCRIPTS_LOCATION="##REPLACE_ON_INSTALL##/" -RECONFIGURE_ROUTE_REFLECTOR = SCRIPTS_LOCATION + "calico_route_reflector.sh" -UPDATE_ETCD_CLUSTER = SCRIPTS_LOCATION + "update_etcd_cluster.sh" - - -def _get_configured_nodes(roles): - with open(NODES_CONFIG, "r") as f: - config = yaml.safe_load(f) - - return [node for node in config["nodes"] if node["role"] in roles] - - -def _get_compute_nodes(): - return _get_configured_nodes(["compute"]) - - -def _get_control_nodes(): - nodes = _get_configured_nodes(["controller", "primary-controller"]) - - for node in nodes: - # Note this does not change the node role in the Fuel deployment, just - # in the list of nodes internal to this script (where we are only - # concerned with the distinction between compute/control nodes, not - # whether a given control node is primary or not). - if node["role"] == "primary-controller": - node["role"] = "controller" - - return nodes - - -class DeploymentChangeHandler(pyinotify.ProcessEvent): - def __init__(self): - super(DeploymentChangeHandler, self).__init__() - self.compute_nodes = _get_compute_nodes() - self.control_nodes = _get_control_nodes() - - def process_IN_MODIFY(self, event): - current_compute_nodes = _get_compute_nodes() - current_control_nodes = _get_control_nodes() - - if current_control_nodes != self.control_nodes: - subprocess.call(RECONFIGURE_ROUTE_REFLECTOR) - subprocess.call(UPDATE_ETCD_CLUSTER) - - elif current_compute_nodes != self.compute_nodes: - subprocess.call(RECONFIGURE_ROUTE_REFLECTOR) - - self.compute_nodes = current_compute_nodes - self.control_nodes = current_control_nodes - - -if __name__ == "__main__": - handler = DeploymentChangeHandler() - watch_manager = pyinotify.WatchManager() - notifier = pyinotify.Notifier(watch_manager, handler) - watch_manager.add_watch(NODES_CONFIG, pyinotify.IN_MODIFY) - notifier.loop() - diff --git a/deployment_scripts/calico_compute.sh b/deployment_scripts/calico_compute.sh deleted file mode 100755 index 6ec65fa..0000000 --- a/deployment_scripts/calico_compute.sh +++ /dev/null @@ -1,173 +0,0 @@ -#!/bin/bash -# Copyright 2015 Metaswitch Networks - -export DEBIAN_FRONTEND=noninteractive - -exec > /tmp/calico_compute.log 2>&1 - -set -x - -echo "Hi, I'm a compute node!" - -this_node_address=$(python get_node_ip.py `hostname`) -controller_node_addresses=$(python get_node_ips_by_role.py controller) - -# Get APT key for binaries.projectcalico.org. - -curl -L http://binaries.projectcalico.org/repo/key | apt-key add - - -# Add source for binaries.projectcalico.org, removing the priority files that -# were automatically created by the fuel plugin installer (the version number -# in the file names causes problems as it contains full stops, and the file -# contents aren't what we want). - -rm -f /etc/apt/preferences.d/calico-fuel-plugin-2.0.0 /etc/apt/sources.list.d/calico-fuel-plugin-2.0.0.list - -cat > /etc/apt/sources.list.d/calico.list <> /etc/apt/preferences.d/calico-fuel -Package: * -Pin: origin binaries.projectcalico.org -Pin-Priority: 1200 -PREFS - -# Add PPA for the etcd packages, and ensure that it has lower priority than -# binaries.projectcalico.org so that we get the fuel versions of the calico -# packages. - -apt-add-repository -y ppa:project-calico/kilo - -cat > /etc/apt/preferences.d/calico-etcd < tmp -mv tmp /etc/init/etcd.conf -cat << EXEC_CMD >> /etc/init/etcd.conf -exec /usr/bin/etcd -proxy on \\ - -listen-client-urls http://127.0.0.1:4001 \\ - -advertise-client-urls http://127.0.0.1:7001 \\ - -initial-cluster ${initial_cluster} -EXEC_CMD -service etcd start - -# Run apt-get upgrade and apt-get dist-upgrade. These commands will -# bring in Calico-specific updates to the OpenStack packages and to -# dnsmasq. - -apt-get -y upgrade -apt-get -y dist-upgrade - -# Open /etc/nova/nova.conf and remove the linuxnet_interface_driver line. - -cp /etc/nova/nova.conf /etc/nova/nova.conf.pre-calico - -sed -i "/^linuxnet_interface_driver/d" /etc/nova/nova.conf -service nova-compute restart - -# Install some extra packages. - -apt-get -y install neutron-common neutron-dhcp-agent nova-api - -# Open /etc/neutron/dhcp_agent.ini in your preferred text editor. In -# the [DEFAULT] section, add the following line: -# -# interface_driver = neutron.agent.linux.interface.RoutedInterfaceDriver - -cp /etc/neutron/dhcp_agent.ini /etc/neutron/dhcp_agent.ini.pre-calico - -sed -i "/^interface_driver/d" /etc/neutron/dhcp_agent.ini - -sed -i "/^\[DEFAULT\]/a\ -interface_driver = neutron.agent.linux.interface.RoutedInterfaceDriver -" /etc/neutron/dhcp_agent.ini - -# Allow BGP connections through the Fuel firewall. We do this before -# installing calico-compute, so that they will be included when the -# calico-compute install script does iptables-save. -iptables -I INPUT 1 -p tcp --dport 179 -j ACCEPT - -# Add sources for BIRD and Ubuntu Precise. - -gpg --keyserver keyserver.ubuntu.com --recv-keys F9C59A45 -gpg -a --export F9C59A45 | apt-key add - - -cat > /etc/apt/sources.list.d/bird.list < /etc/apt/sources.list.d/trusty.list < /tmp/calico_controller.log 2>&1 - -set -x - -echo "Hi, I'm a controller node!" - -this_node_address=$(python get_node_ip.py `hostname`) -controller_node_addresses=$(python get_node_ips_by_role.py controller) - -# Get APT key for binaries.projectcalico.org. - -curl -L http://binaries.projectcalico.org/repo/key | apt-key add - - -# Add source for binaries.projectcalico.org, removing the priority files that -# were automatically created by the fuel plugin installer (the version number -# in the file names causes problems as it contains full stops, and the file -# contents aren't what we want). - -rm -f /etc/apt/preferences.d/calico-fuel-plugin-2.0.0 /etc/apt/sources.list.d/calico-fuel-plugin-2.0.0.list - -cat > /etc/apt/sources.list.d/calico.list <> /etc/apt/preferences.d/calico-fuel -Package: * -Pin: origin binaries.projectcalico.org -Pin-Priority: 1200 -PREFS - -# Add PPA for the etcd packages, and ensure that it has lower priority than -# binaries.projectcalico.org so that we get the fuel versions of the calico -# packages. - -apt-add-repository -y ppa:project-calico/kilo - -cat > /etc/apt/preferences.d/calico-etcd < tmp -mv tmp /etc/init/etcd.conf -cat << EXEC_CMD >> /etc/init/etcd.conf -exec /usr/bin/etcd -name ${this_node_address} \\ - -advertise-client-urls "http://${this_node_address}:2379,http://${this_node_address}:4001" \\ - -listen-client-urls "http://0.0.0.0:2379,http://0.0.0.0:4001" \\ - -listen-peer-urls "http://0.0.0.0:2380" \\ - -initial-advertise-peer-urls "http://${this_node_address}:2380" \\ - -initial-cluster-token fuel-cluster-1 \\ - -initial-cluster ${initial_cluster} \\ - -initial-cluster-state new - -EXEC_CMD - -service etcd start - -# Ensure that the firewall isn't dropping traffic to the ports used by etcd. -iptables -I INPUT 1 -p tcp --dport 2379 -j ACCEPT -iptables -I INPUT 2 -p tcp --dport 2380 -j ACCEPT -iptables -I INPUT 3 -p tcp --dport 4001 -j ACCEPT -iptables-save > /etc/iptables.local -/sbin/iptables-restore < /etc/iptables.local - -# Run apt-get upgrade and apt-get dist-upgrade. These commands will -# bring in Calico-specific updates to the OpenStack packages and to -# dnsmasq. - -apt-get -y upgrade -apt-get -y dist-upgrade - -# Install the calico-control package: - -apt-get -y install calico-control - -# Edit the /etc/neutron/plugins/ml2/ml2_conf.ini file: -# -# Find the line beginning with type_drivers, and change it to -# read type_drivers = local, flat. - -cp /etc/neutron/plugins/ml2/ml2_conf.ini /etc/neutron/plugins/ml2/ml2_conf.ini.pre-calico - -sed -i "/^type_drivers/d" /etc/neutron/plugins/ml2/ml2_conf.ini - -sed -i "/^\[ml2\]/a\ -type_drivers = local, flat -" /etc/neutron/plugins/ml2/ml2_conf.ini - -# Find the line beginning with mechanism_drivers, and change it -# to read mechanism_drivers = calico. - -sed -i "/^mechanism_drivers/d" /etc/neutron/plugins/ml2/ml2_conf.ini - -sed -i "/^\[ml2\]/a\ -mechanism_drivers = calico -" /etc/neutron/plugins/ml2/ml2_conf.ini - -# Find the line beginning with tenant_network_types, and change it -# to read tenant_network_types = local. - -sed -i "/^tenant_network_types/d" /etc/neutron/plugins/ml2/ml2_conf.ini - -sed -i "/^\[ml2\]/a\ -tenant_network_types = local -" /etc/neutron/plugins/ml2/ml2_conf.ini - -# Edit the /etc/neutron/neutron.conf file: -# -# Find the line for the dhcp_agents_per_network setting, -# uncomment it, and set its value to the number of compute nodes -# that you will have (or any number larger than that). This -# allows a DHCP agent to run on every compute node, which Calico -# requires because the networks on different compute nodes are -# not bridged together. - -cp /etc/neutron/neutron.conf /etc/neutron/neutron.conf.pre-calico - -sed -i "/^dhcp_agents_per_network/d" /etc/neutron/neutron.conf - -sed -i "/^\[DEFAULT\]/a\ -dhcp_agents_per_network = 1000 -" /etc/neutron/neutron.conf - -# Remove api_workers and rpc_workers config, so that these default to -# 0. The Calico/OpenStack plugin doesn't currently work if the -# Neutron server is split across multiple OS processes. - -sed -i "/^api_workers/d" /etc/neutron/neutron.conf -sed -i "/^rpc_workers/d" /etc/neutron/neutron.conf - -# Set agent_down_time to 60, instead of Fuel's default setting of 15. -# The Calico/OpenStack plugin reports Felix agent status every 30 -# seconds, based on the HEARTBEAT exchange between the plugin and each -# Felix; and it is recommended that agent_down_time should be double -# the expected reporting interval. - -sed -i "/^agent_down_time/d" /etc/neutron/neutron.conf - -sed -i "/^\[DEFAULT\]/a\ -agent_down_time = 60 -" /etc/neutron/neutron.conf - -# If dnspython is installed, eventlet replaces socket.getaddrinfo() with its -# own version that cannot handle IPv6 addresses. As a workaround, we comment -# out the '::1 localhost' line from /etc/hosts. - -sed -i "s/^::1\(.*\)/#::1\1 #commented out due to dnspython IPv6 issue/" /etc/hosts - -# Restart the neutron server process: - -service neutron-server restart - -# BIRD installation - -gpg --keyserver keyserver.ubuntu.com --recv-keys F9C59A45 -gpg -a --export F9C59A45 | apt-key add - - -cat > /etc/apt/sources.list.d/bird.list < /etc/iptables/rules.v4 - -# Set up a service, calico-fuel-monitor, that will detect changes to the -# deployment and reconfigure the calico components on the controller as -# needed. For example, updating the route reflector configuration after -# compute nodes are added/removed from the deployment. -SERVICE_NAME=calico-fuel-monitor - -# Install the service's dependencies. -apt-get -y install python-pip -pip install pyinotify pyaml - -# During node deployment, the plugin deployment scripts are copied into -# /etc/fuel/plugins/- on the node, and this -# script is run from that directory. -SERVICE_DIR=$(pwd) -sed -i "s@##REPLACE_ON_INSTALL##@${SERVICE_DIR}@" $SERVICE_NAME -chmod +x $SERVICE_NAME - -cat << SERVICE_CFG >> /etc/init/calico-fuel-monitor.conf -# calico-fuel-monitor - daemon to monitor for fuel deployment changes and -# reconfigure the calico components accordingly - -description "Calico daemon to monitor fuel deployment changes" -author "Emma Gordon " - -start on runlevel [2345] -stop on runlevel [016] - -respawn - -script -cd ${SERVICE_DIR} -exec ./${SERVICE_NAME} -end script -SERVICE_CFG - -service $SERVICE_NAME start - -exit 0 diff --git a/deployment_scripts/calico_route_reflector.sh b/deployment_scripts/calico_route_reflector.sh deleted file mode 100755 index af8cfde..0000000 --- a/deployment_scripts/calico_route_reflector.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/bash -# Copyright 2015 Metaswitch Networks - -exec > /tmp/calico_route_reflector.log 2>&1 - -set -x - -echo "Hi, I'm a route_reflector node!" - -this_node_address=$(python get_node_ip.py `hostname`) -controller_node_addresses=$(python get_node_ips_by_role.py controller) - -client_peers=$(python get_node_ips_by_role.py compute) -route_reflector_peers=("${controller_node_addresses[@]/$this_node_address}") - -# Generate basic config for a BIRD BGP route reflector. -cat > /etc/bird/bird.conf <> /etc/bird/bird.conf <> /etc/bird/bird.conf <> /etc/bird/bird.conf <> /etc/bird/bird.conf <{}}) +$subnet_cidr = pick($private_net['L3']['subnet'], '10.20.0.0/16') + +$calico_alt_gateway_br = get_network_role_property('neutron/mesh','interface') +$calico_alt_gateway = try_get_value($network_scheme,"endpoints/${calico_alt_gateway_br}/vendor_specific/provider_gateway") + +# Firewall initials +class { '::firewall':} +Class['::firewall'] -> Firewall<||> +Class['::firewall'] -> Firewallchain<||> + +# iptables -t mangle -N calico-alt-gw-MARK +firewallchain { 'calico-alt-gw-MARK:mangle:IPv4': + ensure => present, +}-> +# iptables -t mangle -A PREROUTING -i tap+ -j calico-alt-gw-MARK +firewall { '010 process traffic from VM instances to outside': + ensure => present, + table => 'mangle', + chain => 'PREROUTING', + iniface => 'tap+', + proto => 'all', + jump => 'calico-alt-gw-MARK', +} -> +#iptables -t mangle -A calico-alt-gw-MARK -d 192.168.111.0/24 -j RETURN +firewall { '011 skip internal traffic': + ensure => present, + table => 'mangle', + chain => 'calico-alt-gw-MARK', + destination => $subnet_cidr, + proto => 'all', + jump => 'RETURN', +} -> +#iptables -t mangle -A calico-alt-gw-MARK -j MARK --set-mark 0x222 +firewall { '012 mark traffic from VM instances to outside': + ensure => present, + table => 'mangle', + chain => 'calico-alt-gw-MARK', + jump => 'MARK', + proto => 'all', + set_mark => $calico_mark +} + +file { '/etc/init/calico-alt-gateway.conf': + ensure => present, + mode => '0644', + owner => 'root', + group => 'root', + content => template('calico/calico-alt-gateway.conf.erb'), +} ~> +service {'calico-alt-gateway': + ensure => running, + enable => true, + hasrestart => false, +} + +# Without such settings source-routing works wrong. For more details +# read the https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt +# Value '2' may be better, but Calico Felix agent is not compotible with '2' +sysctl::value { + 'net.ipv4.conf.all.rp_filter': value => "0"; + "net.ipv4.conf.${calico_alt_gateway_br}.rp_filter": value => "0"; +} + +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment_scripts/puppet/manifests/compute_bird.pp b/deployment_scripts/puppet/manifests/compute_bird.pp new file mode 100644 index 0000000..22d7bea --- /dev/null +++ b/deployment_scripts/puppet/manifests/compute_bird.pp @@ -0,0 +1,36 @@ +notice('MODULAR: calico/compute_bird.pp') + +prepare_network_config(hiera_hash('network_scheme')) +$network_metadata = hiera_hash('network_metadata', {}) + + +# Initial constants +$plugin_name = 'fuel-plugin-calico' +$plugin_settings = hiera_hash("${plugin_name}", {}) +$enable_ipv4 = try_get_value($plugin_settings, 'enable_ipv4', true) +$enable_ipv6 = try_get_value($plugin_settings, 'enable_ipv6', false) +$as_number = try_get_value($plugin_settings, 'as_number', 65001) + +$local_ip = get_network_role_property('neutron/mesh', 'ipaddr') + +$rr_nodes = get_nodes_hash_by_roles($network_metadata, ['calico-rr']) +$rr_nodes_ip = get_node_to_ipaddr_map_by_network_role($rr_nodes, 'neutron/mesh') + +# Firewall initials +class { '::firewall':} +Class['::firewall'] -> Firewall<||> +Class['::firewall'] -> Firewallchain<||> + +firewall { '410 bird': + dport => '179', + proto => 'tcp', + action => 'accept', +} -> +class { 'calico::bird': + template => 'compute', + as_number => $as_number, + enable_ipv4 => $enable_ipv4, + enable_ipv6 => $enable_ipv6, + src_addr => $local_ip, + rr_servers => $rr_nodes_ip, +} diff --git a/deployment_scripts/puppet/manifests/compute_dhcp_agent.pp b/deployment_scripts/puppet/manifests/compute_dhcp_agent.pp new file mode 100644 index 0000000..cb12fb8 --- /dev/null +++ b/deployment_scripts/puppet/manifests/compute_dhcp_agent.pp @@ -0,0 +1,50 @@ +notice('MODULAR: calico/compute_dhcp_agent.pp') + +# stub for task-based deployment +# class neutron { } +# class { 'neutron' : } + +$debug = hiera('debug', true) +$resync_interval = '30' + +# class { '::neutron::agents::dhcp': +# debug => $debug, +# resync_interval => $resync_interval, +# manage_service => false, +# enable_isolated_metadata => true, +# enabled => false, +# } + +# # stub package for 'neutron::agents::dhcp' class +# package { 'neutron': +# name => 'binutils', +# ensure => 'installed', +# } + +package { 'neutron-dhcp-agent': + ensure => 'installed', +} -> +service { 'neutron-dhcp-agent': + ensure => 'stopped', + enable => false +} +tweaks::ubuntu_service_override { 'neutron-dhcp-agent': + package_name => 'neutron-dhcp-agent', +} + +Package['neutron-dhcp-agent'] -> +package { 'calico-dhcp-agent': + ensure => 'installed', +} -> +service { 'calico-dhcp-agent': + ensure => 'running', + enable => true +} +tweaks::ubuntu_service_override { 'calico-dhcp-agent': + package_name => 'calico-dhcp-agent', +} + +neutron_config { 'DEFAULT/use_namespaces': value => false } + +Neutron_config<||> ~> Service['calico-dhcp-agent'] +Neutron_dhcp_agent_config<||> ~> Service['calico-dhcp-agent'] \ No newline at end of file diff --git a/deployment_scripts/puppet/manifests/compute_felix.pp b/deployment_scripts/puppet/manifests/compute_felix.pp new file mode 100644 index 0000000..9d03292 --- /dev/null +++ b/deployment_scripts/puppet/manifests/compute_felix.pp @@ -0,0 +1,41 @@ +notice('MODULAR: calico/compute_felix.pp') + +include calico + +# required, because neutron-dhcp-agent one of dependency of calico-compute +package { 'neutron-dhcp-agent': + ensure => 'installed', +} -> +service { 'neutron-dhcp-agent': + ensure => 'stopped', + enable => false +} +tweaks::ubuntu_service_override { 'neutron-dhcp-agent': + package_name => 'neutron-dhcp-agent', +} + +package { 'calico-felix': + ensure => 'installed', +} -> +package { 'calico-compute': + ensure => 'installed', +} -> +service { 'calico-felix': + ensure => 'running', + enable => true +} +tweaks::ubuntu_service_override { 'calico-felix': + package_name => 'calico-felix', +} + +$etcd_host = '127.0.0.1' +$etcd_port = $calico::params::etcd_port +$metadata_host = '127.0.0.1' +$metadata_port = 8775 + +Package['calico-felix'] -> +file { '/etc/calico/felix.cfg': + ensure => present, + content => template('calico/felix.cfg.erb'), +} ~> +Service['calico-felix'] \ No newline at end of file diff --git a/deployment_scripts/puppet/manifests/compute_metadata_api.pp b/deployment_scripts/puppet/manifests/compute_metadata_api.pp new file mode 100644 index 0000000..b509c93 --- /dev/null +++ b/deployment_scripts/puppet/manifests/compute_metadata_api.pp @@ -0,0 +1,20 @@ +notice('MODULAR: calico/compute_metadata_api.pp') + +# $network_scheme = hiera_hash('network_scheme', {}) +# prepare_network_config($network_scheme) +# $network_metadata = hiera_hash('network_metadata', {}) + +package { 'nova-api-metadata': + name => 'nova-api-metadata', + ensure => 'installed', +} -> +service { 'nova-api-metadata': + enable => true, + ensure => running +} + +# Package['nova-api-metadata'] -> Nova_config<||> +# tweaks::ubuntu_service_override { 'nova-api-metadata': +# package_name => 'nova-api-metadata' +# } +# Nova_config<||> -> Service['nova-api-metadata'] diff --git a/deployment_scripts/puppet/manifests/compute_neutron_nova.pp b/deployment_scripts/puppet/manifests/compute_neutron_nova.pp new file mode 100644 index 0000000..5d5be3a --- /dev/null +++ b/deployment_scripts/puppet/manifests/compute_neutron_nova.pp @@ -0,0 +1,114 @@ +notice('MODULAR: calico/compute_neutron_nova.pp') + +$network_scheme = hiera_hash('network_scheme', {}) +prepare_network_config($network_scheme) +$network_metadata = hiera_hash('network_metadata', {}) + +include calico +include ::nova::params + + +# Initial constants +$plugin_name = 'fuel-plugin-calico' +$plugin_settings = hiera_hash("${plugin_name}", {}) + +$neutron_config = hiera_hash('neutron_config') +$management_vip = hiera('management_vip') +$service_endpoint = hiera('service_endpoint', $management_vip) + +# # LP#1526938 - python-mysqldb supports this, python-pymysql does not +# if $::os_package_type == 'debian' { +# $extra_params = { 'charset' => 'utf8', 'read_timeout' => 60 } +# } else { +# $extra_params = { 'charset' => 'utf8' } +# } + +# $net_role_property = 'neutron/mesh' +# $iface = get_network_role_property($net_role_property, 'phys_dev') +# $physical_net_mtu = pick(get_transformation_property('mtu', $iface[0]), '1500') + +$nova_hash = hiera_hash('nova', {}) +$libvirt_vif_driver = pick($nova_hash['libvirt_vif_driver'], 'nova.virt.libvirt.vif.LibvirtGenericVIFDriver') + +$region_name = hiera('region', 'RegionOne') +$admin_password = try_get_value($neutron_config, 'keystone/admin_password') +$admin_tenant_name = try_get_value($neutron_config, 'keystone/admin_tenant', 'services') +$admin_username = try_get_value($neutron_config, 'keystone/admin_user', 'neutron') +$auth_api_version = 'v3' +$ssl_hash = hiera_hash('use_ssl', {}) + +$admin_identity_protocol = get_ssl_property($ssl_hash, {}, 'keystone', 'admin', 'protocol', 'http') +$admin_identity_address = get_ssl_property($ssl_hash, {}, 'keystone', 'admin', 'hostname', [$service_endpoint, $management_vip]) + +$neutron_internal_protocol = get_ssl_property($ssl_hash, {}, 'neutron', 'internal', 'protocol', 'http') +$neutron_internal_endpoint = get_ssl_property($ssl_hash, {}, 'neutron', 'internal', 'hostname', [hiera('neutron_endpoint', ''), $management_vip]) + +$neutron_auth_url = "${admin_identity_protocol}://${admin_identity_address}:35357/${auth_api_version}" +$neutron_url = "${neutron_internal_protocol}://${neutron_internal_endpoint}:9696" + +$nova_migration_ip = get_network_role_property('nova/migration', 'ipaddr') + +service { 'libvirt' : + ensure => 'running', + enable => true, + name => $::nova::params::libvirt_service_name, + provider => $::nova::params::special_service_provider, +} -> +exec { 'destroy_libvirt_default_network': + command => 'virsh net-destroy default', + onlyif => "virsh net-list | grep -qE '^\s*default\s'", + path => [ '/bin', '/sbin', '/usr/bin', '/usr/sbin' ], + tries => 3, +} -> +exec { 'undefine_libvirt_default_network': + command => 'virsh net-undefine default', + onlyif => "virsh net-list --all | grep -qE '^\s*default\s'", + path => [ '/bin', '/sbin', '/usr/bin', '/usr/sbin' ], + tries => 3, +} + +Service['libvirt'] ~> Exec['destroy_libvirt_default_network'] +Service['libvirt'] ~> Exec['undefine_libvirt_default_network'] + +# script called by qemu needs to manipulate the tap device +file_line { 'clear_emulator_capabilities': + path => '/etc/libvirt/qemu.conf', + line => 'clear_emulator_capabilities = 0', + notify => Service['libvirt'] +} + +class { '::nova::compute::neutron': + libvirt_vif_driver => undef, + force_snat_range => undef, +} + +nova_config { + 'DEFAULT/linuxnet_interface_driver': ensure => absent; + 'DEFAULT/my_ip': value => $nova_migration_ip; +} + +class { '::nova::network::neutron' : + neutron_password => $admin_password, + neutron_project_name => $admin_tenant_name, + neutron_region_name => $region_name, + neutron_username => $admin_username, + neutron_auth_url => $neutron_auth_url, + neutron_url => $neutron_url, + neutron_ovs_bridge => '', +} + +augeas { 'sysctl-net.bridge.bridge-nf-call-arptables': + context => '/files/etc/sysctl.conf', + changes => "set net.bridge.bridge-nf-call-arptables '1'", + before => Service['libvirt'], +} +augeas { 'sysctl-net.bridge.bridge-nf-call-iptables': + context => '/files/etc/sysctl.conf', + changes => "set net.bridge.bridge-nf-call-iptables '1'", + before => Service['libvirt'], +} +augeas { 'sysctl-net.bridge.bridge-nf-call-ip6tables': + context => '/files/etc/sysctl.conf', + changes => "set net.bridge.bridge-nf-call-ip6tables '1'", + before => Service['libvirt'], +} diff --git a/deployment_scripts/puppet/manifests/etcd_proxy.pp b/deployment_scripts/puppet/manifests/etcd_proxy.pp new file mode 100644 index 0000000..06a166c --- /dev/null +++ b/deployment_scripts/puppet/manifests/etcd_proxy.pp @@ -0,0 +1,30 @@ +notice('MODULAR: calico/etcd_proxy.pp') + +prepare_network_config(hiera_hash('network_scheme')) +$network_metadata = hiera_hash('network_metadata', {}) + +include calico + +# Initial constants +$plugin_name = 'fuel-plugin-calico' +$plugin_settings = hiera_hash("${plugin_name}", {}) + +# Firewall initials +class { '::firewall':} +Class['::firewall'] -> Firewall<||> +Class['::firewall'] -> Firewallchain<||> + +firewall { '400 etcd': + dport => [ + $calico::params::etcd_port + ], + proto => 'tcp', + action => 'accept', +} -> +# Deploy etcd cluster member +class { 'calico::etcd': + node_role => 'proxy', + bind_host => $calico::params::mgmt_ip, + bind_port => $calico::params::etcd_port, + cluster_nodes => $calico::params::etcd_servers_named_list, +} diff --git a/deployment_scripts/puppet/manifests/hiera_override.pp b/deployment_scripts/puppet/manifests/hiera_override.pp new file mode 100644 index 0000000..a63119e --- /dev/null +++ b/deployment_scripts/puppet/manifests/hiera_override.pp @@ -0,0 +1,22 @@ +# Manifest that creates hiera config overrride +notice('MODULAR: calico/hiera_override.pp') + +# Initial constants +$plugin_name = 'fuel-plugin-calico' +$plugin_settings = hiera_hash("${plugin_name}", {}) +$network_scheme = hiera_hash("network_scheme", {}) + +# Mangle network_scheme for setup new gateway +if $plugin_settings['metadata']['enabled'] { + if $plugin_settings['network_name'] == 'another' { + $network_name = $plugin_settings['another_network_name'] + } else { + $network_name = $plugin_settings['network_name'] + } + $overrides = remove_ovs_usage($network_scheme) + file {"/etc/hiera/plugins/${plugin_name}.yaml": + ensure => file, + content => inline_template("<%= @overrides %>") + } +} +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment_scripts/puppet/manifests/neutron_networks.pp b/deployment_scripts/puppet/manifests/neutron_networks.pp new file mode 100644 index 0000000..20e490d --- /dev/null +++ b/deployment_scripts/puppet/manifests/neutron_networks.pp @@ -0,0 +1,39 @@ +notice('MODULAR: calico/neutron_networks.pp') + +#include calico + +# Initial constants +$plugin_name = 'fuel-plugin-calico' +$plugin_settings = hiera_hash("${plugin_name}", {}) + +$access_hash = hiera_hash('access', {}) +$tenant_name = try_get_value($access_hash, 'tenant', 'admin') + +# From docs: +# neutron net-create --shared --provider:network_type local calico +# neutron subnet-create --gateway 10.65.0.1 --enable-dhcp --ip-version 4 --name calico-v4 calico 10.65.0/24 + +$net = 'calico' +$subnet = 'calico-v4' +$neutron_config = hiera_hash('neutron_config') +$private_net_name = try_get_value($neutron_config, 'default_private_net', 'admin_internal_net') +$neutron_networks = try_get_value($neutron_config, 'predefined_networks', {}) +$private_net = try_get_value($neutron_networks, $private_net_name, {'L3'=>{}}) +$subnet_cidr = pick($private_net['L3']['subnet'], '10.20.0.0/16') +$subnet_gw = pick($private_net['L3']['gateway'], '10.20.0.1') + +neutron_network { $net : + ensure => 'present', + provider_network_type => 'local', + shared => true, + tenant_name => $tenant_name, +} -> +neutron_subnet { $subnet : + ensure => 'present', + cidr => $subnet_cidr, + network_name => $net, + gateway_ip => $subnet_gw, + enable_dhcp => true, + ip_version => '4', + tenant_name => $tenant_name, +} diff --git a/deployment_scripts/puppet/manifests/neutron_server_config.pp b/deployment_scripts/puppet/manifests/neutron_server_config.pp new file mode 100644 index 0000000..3861c0e --- /dev/null +++ b/deployment_scripts/puppet/manifests/neutron_server_config.pp @@ -0,0 +1,192 @@ +notice('MODULAR: calico/neutron_server_config.pp') + +# stub for task-based deployment +class neutron { } +class { 'neutron' : } + +$network_scheme = hiera_hash('network_scheme', {}) +prepare_network_config($network_scheme) +$network_metadata = hiera_hash('network_metadata', {}) + +include calico + +# Initial constants +$plugin_name = 'fuel-plugin-calico' +$plugin_settings = hiera_hash("${plugin_name}", {}) + +# override neutron options +$override_configuration = hiera_hash('configuration', {}) +override_resources { 'neutron_api_config': + data => $override_configuration['neutron_api_config'] +} ~> Service['neutron-server'] +override_resources { 'neutron_config': + data => $override_configuration['neutron_config'] +} ~> Service['neutron-server'] +override_resources { 'neutron_plugin_ml2': + data => $override_configuration['neutron_plugin_ml2'] +} ~> Service['neutron-server'] + +$neutron_config = hiera_hash('neutron_config') +$neutron_server_enable = pick($neutron_config['neutron_server_enable'], true) +$database_vip = hiera('database_vip') +$management_vip = hiera('management_vip') +$service_endpoint = hiera('service_endpoint', $management_vip) +$nova_endpoint = hiera('nova_endpoint', $management_vip) +$nova_hash = hiera_hash('nova', { }) + +$neutron_primary_controller_roles = hiera('neutron_primary_controller_roles', ['primary-controller']) +$neutron_compute_roles = hiera('neutron_compute_nodes', ['compute']) +$primary_controller = roles_include($neutron_primary_controller_roles) +$compute = roles_include($neutron_compute_roles) + +$db_type = 'mysql' +$db_password = $neutron_config['database']['passwd'] +$db_user = try_get_value($neutron_config, 'database/user', 'neutron') +$db_name = try_get_value($neutron_config, 'database/name', 'neutron') +$db_host = try_get_value($neutron_config, 'database/host', $database_vip) +# LP#1526938 - python-mysqldb supports this, python-pymysql does not +if $::os_package_type == 'debian' { + $extra_params = { 'charset' => 'utf8', 'read_timeout' => 60 } +} else { + $extra_params = { 'charset' => 'utf8' } +} +$db_connection = os_database_connection({ + 'dialect' => $db_type, + 'host' => $db_host, + 'database' => $db_name, + 'username' => $db_user, + 'password' => $db_password, + 'extra' => $extra_params +}) + +$password = $neutron_config['keystone']['admin_password'] +$username = pick($neutron_config['keystone']['admin_user'], 'neutron') +$project_name = pick($neutron_config['keystone']['admin_tenant'], 'services') +$region_name = hiera('region', 'RegionOne') +$auth_endpoint_type = 'internalURL' + +$ssl_hash = hiera_hash('use_ssl', {}) + +$internal_auth_protocol = get_ssl_property($ssl_hash, {}, 'keystone', 'internal', 'protocol', 'http') +$internal_auth_endpoint = get_ssl_property($ssl_hash, {}, 'keystone', 'internal', 'hostname', [$service_endpoint, $management_vip]) + +$admin_auth_protocol = get_ssl_property($ssl_hash, {}, 'keystone', 'admin', 'protocol', 'http') +$admin_auth_endpoint = get_ssl_property($ssl_hash, {}, 'keystone', 'admin', 'hostname', [$service_endpoint, $management_vip]) + +$nova_internal_protocol = get_ssl_property($ssl_hash, {}, 'nova', 'internal', 'protocol', 'http') +$nova_internal_endpoint = get_ssl_property($ssl_hash, {}, 'nova', 'internal', 'hostname', [$nova_endpoint]) + +$auth_api_version = 'v2.0' +$auth_uri = "${internal_auth_protocol}://${internal_auth_endpoint}:5000/" +$auth_url = "${internal_auth_protocol}://${internal_auth_endpoint}:35357/" +$nova_admin_auth_url = "${admin_auth_protocol}://${admin_auth_endpoint}:35357/" +$nova_url = "${nova_internal_protocol}://${nova_internal_endpoint}:8774/v2" + +$workers_max = hiera('workers_max', 16) +$service_workers = pick($neutron_config['workers'], min(max($::processorcount, 1), $workers_max)) + +$neutron_advanced_config = hiera_hash('neutron_advanced_configuration', { }) +$enable_qos = pick($neutron_advanced_config['neutron_qos'], false) + +if $enable_qos { + $qos_notification_drivers = 'message_queue' + $extension_drivers = ['port_security', 'qos'] +} else { + $qos_notification_drivers = undef + $extension_drivers = ['port_security'] +} + +$nova_auth_user = pick($nova_hash['user'], 'nova') +$nova_auth_password = $nova_hash['user_password'] +$nova_auth_tenant = pick($nova_hash['tenant'], 'services') + +$net_role_property = 'neutron/mesh' +$iface = get_network_role_property($net_role_property, 'phys_dev') +$physical_net_mtu = pick(get_transformation_property('mtu', $iface[0]), '1500') + +Package['neutron'] ~> +package { 'calico-control': + ensure => 'installed', +} +Package['calico-control'] -> Class['::neutron::server'] +Package['calico-control'] -> Class['::neutron::plugins::ml2'] + +class { '::neutron::plugins::ml2': + type_drivers => ['local', 'flat'], + tenant_network_types => 'local', + mechanism_drivers => ['calico'], + flat_networks => ['*'], + #network_vlan_ranges => $network_vlan_ranges, + #tunnel_id_ranges => [], + #vxlan_group => $vxlan_group, + #vni_ranges => $tunnel_id_ranges, + path_mtu => $physical_net_mtu, + extension_drivers => $extension_drivers, + #supported_pci_vendor_devs => $pci_vendor_devs, + sriov_agent_required => false, + enable_security_group => true, + firewall_driver => 'neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver', +} + +class { '::neutron::server': + sync_db => $primary_controller, + + username => $username, + password => $password, + project_name => $project_name, + region_name => $region_name, + auth_url => $auth_url, + auth_uri => $auth_uri, + + database_connection => $db_connection, + database_max_retries => hiera('max_retries'), + database_idle_timeout => hiera('idle_timeout'), + database_max_pool_size => hiera('max_pool_size'), + database_max_overflow => hiera('max_overflow'), + database_retry_interval => '2', + + agent_down_time => 60, # it's a requirements of calico-plugin + allow_automatic_l3agent_failover => false, + l3_ha => false, + + api_workers => 0, # it's a requirements of + rpc_workers => 0, # calico-plugin + + router_distributed => false, + qos_notification_drivers => $qos_notification_drivers, + enabled => true, + manage_service => true, +} + +Package['neutron'] ~> +augeas { "dhcp_agents_per_network": + #context => "/files/etc/neutron/neutron.conf", + incl => "/etc/neutron/neutron.conf", + lens => 'Puppet.lns', + changes => [ + "set DEFAULT/dhcp_agents_per_network ${calico::params::compute_nodes_count}", + ], +} ~> Service['neutron-server'] + +include ::neutron::params +tweaks::ubuntu_service_override { $::neutron::params::server_service: + package_name => $neutron::params::server_package ? { + false => $neutron::params::package_name, + default => $neutron::params::server_package + } +} + +class { '::neutron::server::notifications': + nova_url => $nova_url, + auth_url => $nova_admin_auth_url, + username => $nova_auth_user, + project_name => $nova_auth_tenant, + password => $nova_auth_password, + region_name => $region_name, +} + +# Stub for Nuetron package +package { 'neutron': + name => 'binutils', + ensure => 'installed', +} diff --git a/deployment_scripts/puppet/manifests/private_gateway_check.pp b/deployment_scripts/puppet/manifests/private_gateway_check.pp new file mode 100644 index 0000000..b61e609 --- /dev/null +++ b/deployment_scripts/puppet/manifests/private_gateway_check.pp @@ -0,0 +1,12 @@ +notice('MODULAR: calico/private_gateway_check.pp') + +$network_scheme = hiera_hash('network_scheme') +prepare_network_config($network_scheme) +$calico_alt_gateway_br = get_network_role_property('neutron/mesh','interface') +$calico_alt_gateway = try_get_value($network_scheme,"endpoints/${calico_alt_gateway_br}/vendor_specific/provider_gateway") + +if ! is_ip_address($calico_alt_gateway) { + fail("Gateway for Private network does not specified or wrong !!!") +} + +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment_scripts/puppet/manifests/repo_setup.pp b/deployment_scripts/puppet/manifests/repo_setup.pp new file mode 100644 index 0000000..f8ac704 --- /dev/null +++ b/deployment_scripts/puppet/manifests/repo_setup.pp @@ -0,0 +1,25 @@ +notice('MODULAR: calico/repo_setup.pp') + +# Initial constants +$plugin_name = 'fuel-plugin-calico' +$plugin_settings = hiera_hash("${plugin_name}", {}) + +# Bird PPA +apt::source { 'bird-repo': + location => 'http://ppa.launchpad.net/cz.nic-labs/bird/ubuntu', + repos => 'main', + #release => 'trusty', + include => { 'src' => false }, +} + +# Calico PPA +apt::source { 'calico-repo': + #location => "http://ppa.launchpad.net/project-calico/stable/ubuntu", + location => "http://ppa.launchpad.net/project-calico/calico-1.4/ubuntu", + repos => 'main', + #release => 'trusty', + include => { 'src' => false }, +} + +Apt::Source<||> ~> Exec<| title == 'apt_update' |> +Exec<| title == 'apt_update' |> -> Package<||> diff --git a/deployment_scripts/puppet/manifests/role_etcd.pp b/deployment_scripts/puppet/manifests/role_etcd.pp new file mode 100644 index 0000000..1e59f8c --- /dev/null +++ b/deployment_scripts/puppet/manifests/role_etcd.pp @@ -0,0 +1,36 @@ +notice('MODULAR: calico/etcd.pp') + +prepare_network_config(hiera_hash('network_scheme')) +$network_metadata = hiera_hash('network_metadata', {}) + +include calico + +# Initial constants +$plugin_name = 'fuel-plugin-calico' +$plugin_settings = hiera_hash("${plugin_name}", {}) +$cluster_info = hiera_hash('cluster', {}) +$cluster_token = try_get_value($cluster_info, 'name', 'openstack-calico-cluster') + +# Firewall initials +class { '::firewall':} +Class['::firewall'] -> Firewall<||> +Class['::firewall'] -> Firewallchain<||> + +firewall { '400 etcd': + dport => [ + $calico::params::etcd_port, + $calico::params::etcd_peer_port + ], + proto => 'tcp', + action => 'accept', +} -> +# Deploy etcd cluster member +class { 'calico::etcd': + node_role => 'server', + bind_host => $calico::params::mgmt_ip, + bind_port => $calico::params::etcd_port, + peer_host => $calico::params::mgmt_ip, + peer_port => $calico::params::etcd_peer_port, + cluster_nodes => $calico::params::etcd_servers_named_list, + cluster_token => $cluster_token +} diff --git a/deployment_scripts/puppet/manifests/role_rr.pp b/deployment_scripts/puppet/manifests/role_rr.pp new file mode 100644 index 0000000..1aa09ae --- /dev/null +++ b/deployment_scripts/puppet/manifests/role_rr.pp @@ -0,0 +1,43 @@ +notice('MODULAR: calico/rr_bird.pp') + +prepare_network_config(hiera_hash('network_scheme')) +$network_metadata = hiera_hash('network_metadata', {}) + + +# Initial constants +$plugin_name = 'fuel-plugin-calico' +$plugin_settings = hiera_hash("${plugin_name}", {}) +$enable_ipv4 = try_get_value($plugin_settings, 'enable_ipv4', true) +$enable_ipv6 = try_get_value($plugin_settings, 'enable_ipv6', false) +$as_number = try_get_value($plugin_settings, 'as_number', 65001) +if try_get_value($plugin_settings, 'enable_external_peering', false) { + $ext_peers = convert_external_peers(try_get_value($plugin_settings, 'external_peers', '')) +} else { + $ext_peers = {} +} + +$local_ip = get_network_role_property('neutron/mesh', 'ipaddr') + +$compute_nodes = get_nodes_hash_by_roles($network_metadata, ['compute']) +$compute_nodes_ip = get_node_to_ipaddr_map_by_network_role($compute_nodes, 'neutron/mesh') + +# Firewall initials +class { '::firewall':} +Class['::firewall'] -> Firewall<||> +Class['::firewall'] -> Firewallchain<||> + +firewall { '410 bird': + dport => '179', + proto => 'tcp', + action => 'accept', +} -> +class { 'calico::bird': + template => 'rr', + as_number => $as_number, + enable_ipv4 => $enable_ipv4, + enable_ipv6 => $enable_ipv6, + src_addr => $local_ip, + rr_clients => $compute_nodes_ip, + rr_servers => {}, + ext_peers => $ext_peers, +} diff --git a/deployment_scripts/puppet/modules/calico/Modulefile b/deployment_scripts/puppet/modules/calico/Modulefile new file mode 100644 index 0000000..2015005 --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/Modulefile @@ -0,0 +1,12 @@ +name 'calico' +version '0.1.0' +source 'UNKNOWN' +author 'mirantis' +license 'Apache License, Version 2.0' +summary 'UNKNOWN' +description 'UNKNOWN' +project_page 'UNKNOWN' + +## Add dependencies, if any: +# dependency 'username/name', '>= 1.2.0' +dependency 'puppetlabs/stdlib', '>=4.6.0' diff --git a/deployment_scripts/puppet/modules/calico/lib/puppet/parser/functions/convert_external_peers.rb b/deployment_scripts/puppet/modules/calico/lib/puppet/parser/functions/convert_external_peers.rb new file mode 100644 index 0000000..5cb9f02 --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/lib/puppet/parser/functions/convert_external_peers.rb @@ -0,0 +1,28 @@ +Puppet::Parser::Functions::newfunction( :convert_external_peers, + :type => :rvalue, :doc => <<-EOS + This function get text in format + name:asnum:ipaddr:flags... + and convert to hash, used into generate_bgp_peers() + { + peer_name => { + ipaddr => '1.2.3.4', + as_number => '64646' + } + } + + EOS + ) do |argv| + + if argv.size != 1 + raise( + Puppet::ParseError, + "convert_external_peers(): Wrong number of arguments. Should be one." + ) + end + + peers = argv[0] + as_number = argv[1] + + Hash[*peers.split(/\n/).map{|v| v.gsub(/\s+/, "")}.reject{|c| c.empty?}.map{|v| v.split(':')}.reject{|v| v.size<3}.map{|l| [l[0],{'as_number'=>l[1],'ipaddr'=> l[2]}]}.flatten] +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment_scripts/puppet/modules/calico/lib/puppet/parser/functions/convert_internal_peers.rb b/deployment_scripts/puppet/modules/calico/lib/puppet/parser/functions/convert_internal_peers.rb new file mode 100644 index 0000000..f0afbb7 --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/lib/puppet/parser/functions/convert_internal_peers.rb @@ -0,0 +1,51 @@ +Puppet::Parser::Functions::newfunction( :convert_internal_peers, + :type => :rvalue, :doc => <<-EOS + This function get peers name-to-ipaddr map, as_number + and convert to hassh, used into generate_bgp_peers() + Usage: + convert_internal_peers( + $peers_hash, + $local_as_number, + ) + + Hash + { + peer_name -> '1.2.3.4' + } + will be converted to + { + peer_name => { + ipaddr => '1.2.3.4', + as_number => '64646' + } + } + + EOS + ) do |argv| + + if argv.size != 2 + raise( + Puppet::ParseError, + "convert_internal_peers(): Wrong number of arguments. Should be two." + ) + end + if !argv[0].is_a?(Hash) + raise( + Puppet::ParseError, + "convert_internal_peers(): Wrong peers map." + ) + end + + peers = argv[0] + as_number = argv[1] + + rv = {} + peers.each do |name, ipaddr| + rv[name] = { + 'ipaddr' => ipaddr, + 'as_number' => as_number, + } + end + return rv +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment_scripts/puppet/modules/calico/lib/puppet/parser/functions/generate_bgp_peers.rb b/deployment_scripts/puppet/modules/calico/lib/puppet/parser/functions/generate_bgp_peers.rb new file mode 100644 index 0000000..ea22755 --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/lib/puppet/parser/functions/generate_bgp_peers.rb @@ -0,0 +1,55 @@ +Puppet::Parser::Functions::newfunction( :generate_bgp_peers, + :type => :statement, :doc => <<-EOS + This function get internal peers map, connectivity options + and create corresponded resources. + Usage: + generate_bgp_peers( + $peers_hash, + $template_name, + $local_ipaddr, + $local_as_number, + ) + + Peers_hash should be in format: + { + peer_name => { + ipaddr => '1.2.3.4', + as_number => '64646' + } + } + EOS + ) do |argv| + + if argv.size != 4 + raise( + Puppet::ParseError, + "generate_bgp_peers(): Wrong number of arguments. Should be four." + ) + end + if !argv[0].is_a?(Hash) + raise( + Puppet::ParseError, + "generate_bgp_peers(): Wrong peers map." + ) + end + + peers = argv[0] + template = argv[1] + local_ipaddr = argv[2] + local_as_number = argv[3] + + resources = {} + peers.each do |name, peer_hash| + #file_name = "/etc/bird/peers/#{template}__#{name}.conf" + resources[name] = { + 'template' => template, + 'local_ipaddr' => local_ipaddr, + 'remote_ipaddr' => peer_hash['ipaddr'], + 'local_as_number' => local_as_number, + 'remote_as_number' => peer_hash['as_number'], + } + end + function_create_resources(['calico::bird::bgp_peer_record', resources]) + return true +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment_scripts/puppet/modules/calico/lib/puppet/parser/functions/remove_ovs_usage.rb b/deployment_scripts/puppet/modules/calico/lib/puppet/parser/functions/remove_ovs_usage.rb new file mode 100644 index 0000000..4a391c0 --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/lib/puppet/parser/functions/remove_ovs_usage.rb @@ -0,0 +1,65 @@ +require 'yaml' + +Puppet::Parser::Functions::newfunction( :remove_ovs_usage, + :type => :rvalue, :doc => <<-EOS + This function get network_scheme and returns mangled + network scheme without ovs-based elements. + EOS + ) do |argv| + + def bridge_name_max_len + 15 + end + + if argv.size != 1 + raise( + Puppet::ParseError, + "remove_ovs_usage(): Wrong number of arguments. Should be two." + ) + end + if !argv[0].is_a?(Hash) + raise( + Puppet::ParseError, + "remove_ovs_usage(): Wrong network_scheme. Should be non-empty Hash." + ) + end + if argv[0]['version'].to_s.to_f < 1.1 + raise( + Puppet::ParseError, + "remove_ovs_usage(): You network_scheme hash has wrong format.\nThis parser can work with v1.1 format, please convert you config." + ) + end + + network_scheme = argv[0] + rv = { + 'use_ovs' => false + } + overrides = [] + + network_scheme['transformations'].each do |tr| + if tr['provider'] == 'ovs' + if tr['action'] == 'add-patch' + overrides << { + 'action' => 'override', + 'override' => "patch-#{tr['bridges'][0]}:#{tr['bridges'][1]}", + 'provider' => 'lnx' + } + else + overrides << { + 'action' => 'override', + 'override' => tr['name'], + 'provider' => 'lnx' + } + end + end + end + + if ! overrides.empty? + rv['network_scheme'] = { + 'transformations' => overrides + } + end + + return rv.to_yaml() + "\n" +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment_scripts/puppet/modules/calico/manifests/bird.pp b/deployment_scripts/puppet/modules/calico/manifests/bird.pp new file mode 100644 index 0000000..e873e4c --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/manifests/bird.pp @@ -0,0 +1,95 @@ +# Copyright 2015 Mirantis, Inc. +# +# Licensed 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. + +class calico::bird ( + $template, + $src_addr, + $as_number = '64511', + $enable_ipv4 = true, + $enable_ipv6 = false, + $rr_clients = {}, + $rr_servers = {}, + $ext_peers = {}, +) { + + include ::calico + + tweaks::ubuntu_service_override { 'bird': + package_name => 'bird', + } + + tweaks::ubuntu_service_override { 'bird6': + package_name => 'bird', + } + + package { 'bird': + ensure => installed, + } -> + file { '/etc/bird': + ensure => directory, + } -> + file { '/etc/bird/peers': + ensure => directory, + } -> + file { '/etc/bird/custom.conf': + ensure => present, + } -> + file { '/etc/bird/calico_os_filters.conf': + ensure => present, + mode => '0644', + owner => 'root', + group => 'root', + content => template("calico/bird-calico_os-filters.conf.erb"), + } -> + file { '/etc/bird/bird.conf': + ensure => present, + mode => '0644', + owner => 'root', + group => 'root', + content => template("calico/bird-${template}.conf.erb"), + } + + # generate peer-config-files + generate_bgp_peers(convert_internal_peers($rr_servers, $as_number), 'rr', $src_addr, $as_number) + generate_bgp_peers(convert_internal_peers($rr_clients, $as_number), 'compute', $src_addr, $as_number) + generate_bgp_peers($ext_peers, 'ext', $src_addr, $as_number) + + if $enable_ipv4 { + Package['bird'] ~> + service { 'bird': + ensure => running, + enable => true, + hasrestart => false, + restart => '/usr/sbin/birdc configure' + } + File['/etc/bird/calico_os_filters.conf'] ~> Service['bird'] + File['/etc/bird/custom.conf'] ~> Service['bird'] + File['/etc/bird/bird.conf'] ~> Service['bird'] + } + + if $enable_ipv6 { + Package['bird'] ~> + service { 'bird6': + ensure => running, + enable => true, + hasrestart => false, + restart => '/usr/sbin/birdc6 configure' + } + File['/etc/bird/calico_os_filters.conf'] ~> Service['bird6'] + File['/etc/bird/custom.conf'] ~> Service['bird6'] + File['/etc/bird/bird6.conf'] ~> Service['bird6'] + } + +} +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment_scripts/puppet/modules/calico/manifests/bird/bgp_peer_record.pp b/deployment_scripts/puppet/modules/calico/manifests/bird/bgp_peer_record.pp new file mode 100644 index 0000000..2eb35ab --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/manifests/bird/bgp_peer_record.pp @@ -0,0 +1,35 @@ +define calico::bird::bgp_peer_record ( + $local_ipaddr, + $remote_ipaddr, + $local_as_number, + $remote_as_number, + $include = false, + $ensure = 'present', + $template = 'ext', +) { + include ::calico::params + $peer_config_path = "/etc/bird/peers/${template}__${name}.conf" + file { "${peer_config_path}": + ensure => $ensure, + require => File['/etc/bird/peers'], + before => File['/etc/bird/bird.conf'], + notify => Service['bird'], + content => template("calico/bird-peer-${template}.conf.erb"), + } + if $include { + file_line {"": + line => "include ${peer_config_path};", + path => '/etc/bird/bird.conf', + #after => undef, + #ensure => 'present', + #match => undef, # /.*match/ + #multiple => undef, # 'true' or 'false' + #name => undef, + #replace => true, # 'true' or 'false' + require => File['/etc/bird/bird.conf'], + notify => Service['bird'] + } + } +} + +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment_scripts/puppet/modules/calico/manifests/etcd.pp b/deployment_scripts/puppet/modules/calico/manifests/etcd.pp new file mode 100644 index 0000000..eaea60b --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/manifests/etcd.pp @@ -0,0 +1,77 @@ +# Copyright 2015 Mirantis, Inc. +# +# Licensed 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. + +class calico::etcd ( + $node_name = $::hostname, + $node_role, + $bind_host = $::ipaddress, + $bind_port = '4001', + $peer_host = $::ipaddress, + $peer_port = '2380', + $cluster_nodes = undef, + $cluster_token = 'fuel-cluster-1' +) { + +case $node_role { + 'proxy': { + $etcd_cmd_opts = "--proxy on \ +--initial-cluster=${cluster_nodes} \ +>>/var/log/etcd.log 2>&1" + } + 'server': { + $etcd_cmd_opts = "--name=${node_name} \ +--advertise-client-urls=http://${bind_host}:${bind_port} \ +--listen-client-urls=http://127.0.0.1:${bind_port},http://${bind_host}:${bind_port} \ +--listen-peer-urls=http://127.0.0.1:${peer_port},http://${peer_host}:${peer_port} \ +--initial-cluster-token='${cluster_token}' \ +--initial-cluster=${cluster_nodes} \ +--initial-cluster-state=new \ +--initial-advertise-peer-urls=http://${peer_host}:${peer_port} \ +>>/var/log/etcd.log 2>&1" + } + default: { + } +} + + tweaks::ubuntu_service_override { 'etcd': + package_name => 'etcd', + } + + package { ['etcd','python-etcd']: + ensure => installed, + } -> + + file { '/var/log/etcd.log': + ensure => present, + mode => '0644', + owner => 'etcd', + group => 'etcd', + } -> + + file { '/etc/init/etcd.conf': + ensure => present, + mode => '0644', + owner => 'root', + group => 'root', + content => template('calico/etcd.conf.erb'), + } ~> + + service { 'etcd': + ensure => 'running', + enable => true, + provider => 'upstart' + } + +} +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment_scripts/puppet/modules/calico/manifests/init.pp b/deployment_scripts/puppet/modules/calico/manifests/init.pp new file mode 100644 index 0000000..9ebdf7d --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/manifests/init.pp @@ -0,0 +1,20 @@ +# Copyright 2015 Mirantis, Inc. +# +# Licensed 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. + +class calico { + +include calico::params + +} +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment_scripts/puppet/modules/calico/manifests/params.pp b/deployment_scripts/puppet/modules/calico/manifests/params.pp new file mode 100644 index 0000000..c70a72b --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/manifests/params.pp @@ -0,0 +1,43 @@ +# Copyright 2016 Mirantis, Inc. +# +# Licensed 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. + +class calico::params { + + # Network + $network_scheme = hiera_hash('network_scheme', {}) + $network_metadata = hiera_hash('network_metadata', {}) + prepare_network_config($network_scheme) + + # current node params + $node = hiera('node') + $roles = hiera('roles') + $mgmt_ip = get_network_role_property('mgmt/vip', 'ipaddr') + + # computes + $compute_nodes = get_nodes_hash_by_roles($network_metadata, ['compute']) + $compute_nodes_count = size($compute_nodes) + + # etcd nodes + $etcd_nodes = get_nodes_hash_by_roles($network_metadata, ['calico-etcd']) + $etcd_nodes_map = get_node_to_ipaddr_map_by_network_role($etcd_nodes, 'mgmt/vip') + $etcd_nodes_ips = ipsort(values($etcd_nodes_map)) + + # etcd daemon settings + $etcd_port = '4001' + $etcd_peer_port = '2380' + $etcd_servers = suffix(prefix($etcd_nodes_ips, 'http://'), ":${etcd_port}") + $etcd_servers_list = join($etcd_servers, ',') + $etcd_servers_named_list = join(suffix(join_keys_to_values($etcd_nodes_map,"=http://"), ":${etcd_peer_port}"), ',') +} +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment_scripts/puppet/modules/calico/spec/spec_helper.rb b/deployment_scripts/puppet/modules/calico/spec/spec_helper.rb new file mode 100644 index 0000000..5fda588 --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/spec/spec_helper.rb @@ -0,0 +1,17 @@ +dir = File.expand_path(File.dirname(__FILE__)) +$LOAD_PATH.unshift File.join(dir, 'lib') + +require 'mocha' +require 'puppet' +require 'rspec' +require 'spec/autorun' + +Spec::Runner.configure do |config| + config.mock_with :mocha +end + +# We need this because the RAL uses 'should' as a method. This +# allows us the same behaviour but with a different method name. +class Object + alias :must :should +end diff --git a/deployment_scripts/puppet/modules/calico/templates/bird-calico_os-filters.conf.erb b/deployment_scripts/puppet/modules/calico/templates/bird-calico_os-filters.conf.erb new file mode 100644 index 0000000..9ed46df --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/templates/bird-calico_os-filters.conf.erb @@ -0,0 +1,18 @@ +# We are only going to export routes from Calico interfaces. +# Currently, 'tap*' is used by the OpenStack implimentation +# and 'cali*' is used by the docker implimentation. +# dummy1 is the interface that bare metal "service" addresses +# should be bound to if they should be exported. +# This will need to be updated as we add new interface names. +# +# Also filter out default, just in case. +# +# We should automate the build of this out of variables when +# we have time. + +filter calico_openstack__export_bgp { + if ( (ifname ~ "tap*") || (ifname ~ "cali*") || (ifname ~ "dummy1") ) then { + if net != 0.0.0.0/0 then accept; + } + reject; +} diff --git a/deployment_scripts/puppet/modules/calico/templates/bird-compute.conf.erb b/deployment_scripts/puppet/modules/calico/templates/bird-compute.conf.erb new file mode 100644 index 0000000..a5068cb --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/templates/bird-compute.conf.erb @@ -0,0 +1,29 @@ +router id <%= @src_addr %>; +listen bgp address <%= @src_addr %>; + +include "/etc/bird/calico_os_filters.conf"; + +# Configure synchronization between BIRD's routing tables and the +# kernel. +protocol kernel { + learn; # Learn all alien routes from the kernel + persist; # Don't remove routes on bird shutdown + scan time 2; # Scan kernel routing table every 2 seconds + import all; + graceful restart; + export all; # Default is export none +} + +# Watch interface up/down events. +protocol device { + scan time 2; # Scan interfaces every 2 seconds +} + +protocol direct { + debug all; + interface "br-mesh"; +} + +<%- @rr_servers.each do |name, ipaddr| -%> +include "/etc/bird/peers/rr__<%= name %>.conf"; +<%- end -%> diff --git a/deployment_scripts/puppet/modules/calico/templates/bird-peer-compute.conf.erb b/deployment_scripts/puppet/modules/calico/templates/bird-peer-compute.conf.erb new file mode 100644 index 0000000..f4bafa2 --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/templates/bird-peer-compute.conf.erb @@ -0,0 +1,10 @@ +protocol bgp '<%= @name %>' { + local as <%= @local_as_number %>; + neighbor <%= @remote_ipaddr %> as <%= @remote_as_number %>; + description "RR-client <%= @name %>"; + multihop; + rr client; + import all; + export all; + source address <%= @local_ipaddr %>; +} diff --git a/deployment_scripts/puppet/modules/calico/templates/bird-peer-ext.conf.erb b/deployment_scripts/puppet/modules/calico/templates/bird-peer-ext.conf.erb new file mode 100644 index 0000000..84d55e5 --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/templates/bird-peer-ext.conf.erb @@ -0,0 +1,10 @@ +protocol bgp '<%= @name %>' { + local as <%= @local_as_number %>; + neighbor <%= @remote_ipaddr %> as <%= @remote_as_number %>; + description "Ext. peer <%= @name %>"; + multihop; + import none; + export all; + next hop keep; + source address <%= @local_ipaddr %>; +} diff --git a/deployment_scripts/puppet/modules/calico/templates/bird-peer-rr.conf.erb b/deployment_scripts/puppet/modules/calico/templates/bird-peer-rr.conf.erb new file mode 100644 index 0000000..60638c8 --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/templates/bird-peer-rr.conf.erb @@ -0,0 +1,11 @@ +protocol bgp '<%= @name %>' { + local as <%= @local_as_number %>; + neighbor <%= @remote_ipaddr %> as <%= @remote_as_number %>; + description "Route Reflector <%= @name %>"; + multihop; + import all; + export filter calico_openstack__export_bgp; + next hop self; # Disable next hop processing and always advertise our + # local address as nexthop + source address <%= @local_ipaddr %>; +} diff --git a/deployment_scripts/puppet/modules/calico/templates/bird-rr.conf.erb b/deployment_scripts/puppet/modules/calico/templates/bird-rr.conf.erb new file mode 100644 index 0000000..a7f034e --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/templates/bird-rr.conf.erb @@ -0,0 +1,26 @@ +# Configure logging +log syslog { debug, trace, info, remote, warning, error, auth, fatal, bug }; +log stderr all; +#log "tmp" all; +# Override router ID +router id <%= @src_addr %>; + +include "/etc/bird/calico_os_filters.conf"; + +# Turn on global debugging of all protocols +debug protocols all; +# This pseudo-protocol watches all interface up/down events. +protocol device { + scan time 2; # Scan interfaces every 2 seconds +} + +# Include custom config +include "/etc/bird/custom.conf"; + +<%- @rr_clients.each do |name, ipaddr| -%> +include "/etc/bird/peers/compute__<%= name %>.conf"; +<%- end -%> + +<%- @ext_peers.each do |name, peer| -%> +include "/etc/bird/peers/ext__<%= name %>.conf"; +<%- end -%> diff --git a/deployment_scripts/puppet/modules/calico/templates/calico-alt-gateway.conf.erb b/deployment_scripts/puppet/modules/calico/templates/calico-alt-gateway.conf.erb new file mode 100644 index 0000000..93bdd94 --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/templates/calico-alt-gateway.conf.erb @@ -0,0 +1,13 @@ +description "calico-alt-gateway" +author "Alternative default gateway for Calico network" + +#start on stopped rc RUNLEVEL=[2345] +start on (net-device-up and started etcd) +#stop on runlevel [!2345] + +#respawn + +script + ip r add default via <%= @calico_alt_gateway %> table <%= @calico_mark %> + ip rule add fwmark <%= @calico_mark %> table <%= @calico_mark %> +end script diff --git a/deployment_scripts/puppet/modules/calico/templates/etcd.conf.erb b/deployment_scripts/puppet/modules/calico/templates/etcd.conf.erb new file mode 100644 index 0000000..2f9dc8c --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/templates/etcd.conf.erb @@ -0,0 +1,15 @@ +# vim:set ft=upstart ts=2 et: +description "etcd" +author "etcd maintainers" + +start on stopped rc RUNLEVEL=[2345] +stop on runlevel [!2345] + +respawn + +setuid etcd + +env ETCD_DATA_DIR=/var/lib/etcd +export ETCD_DATA_DIR + +exec /usr/bin/etcd <%=@etcd_cmd_opts %> diff --git a/deployment_scripts/puppet/modules/calico/templates/felix.cfg.erb b/deployment_scripts/puppet/modules/calico/templates/felix.cfg.erb new file mode 100644 index 0000000..c87cac9 --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/templates/felix.cfg.erb @@ -0,0 +1,6 @@ +[global] +EtcdAddr = <%= @etcd_host %>:<%= @etcd_port %> +#FelixHostname = hostname +MetadataAddr = <%= @metadata_host %> +MetadataPort = <%= @metadata_port %> +InterfacePrefix = tap diff --git a/deployment_scripts/puppet/modules/calico/tests/init.pp b/deployment_scripts/puppet/modules/calico/tests/init.pp new file mode 100644 index 0000000..4e799ab --- /dev/null +++ b/deployment_scripts/puppet/modules/calico/tests/init.pp @@ -0,0 +1,12 @@ +# The baseline for module testing used by Puppet Labs is that each manifest +# should have a corresponding test manifest that declares that class or defined +# type. +# +# Tests are then run by using puppet apply --noop (to check for compilation +# errors and view a log of events) or by fully applying the test in a virtual +# environment (to compare the resulting system state to the desired state). +# +# Learn more about module testing here: +# http://docs.puppetlabs.com/guides/tests_smoke.html +# +include calico diff --git a/deployment_scripts/remove_default_networks.sh b/deployment_scripts/remove_default_networks.sh deleted file mode 100755 index 15c633e..0000000 --- a/deployment_scripts/remove_default_networks.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash -# This script removes default network config created in OpenStack as part of a -# Fuel deployment. These networks do not work for instance creation with -# Calico, so need to be removed. - -# OpenStack authentication and authorization requires environment variables -# contained in the openrc file, this will allow us to issue commands via the -# neutron API. -source /root/openrc - -# Details of the default networks/routers created on Fuel deployment of a -# Mirantis OpenStack environment. -DEFAULT_NET=net04 -DEFAULT_NET_EXT=net04_ext -DEFAULT_ROUTER=router04 - -# DEFAULT_NET_EXT is set as the gateway for DEFAULT_ROUTER, we must clear that -# before we can delete the network. -neutron router-gateway-clear $DEFAULT_ROUTER -neutron net-delete $DEFAULT_NET_EXT - -# DEFAULT_NET cannot be deleted until all ports configured on the network have -# been removed. We get details of the configured ports from the "neutron port-list" -# command, whose output is of the form: -# +-----+------+-------------------+-----------------------------------------------+ -# | id | name | mac_address | fixed_ips | -# +-----+------+-------------------+-----------------------------------------------+ -# | foo | | fa:16:3e:ae:70:4e | {"subnet_id": "bar", "ip_address": "a.b.c.d"} | -# +-----+------+-------------------+-----------------------------------------------+ -port_ids=$(neutron port-list | grep "|" | grep -v "fixed_ips" | cut -d " " -f 2) -for port_id in "${port_ids[@]}" -do - neutron port-delete $port_id - if [[ $? != 0 ]]; then - # One of the ports is associated with the interface for the default router. - # This causes port deletion to fail. So we delete the interface on the - # router (this also removes the port). - neutron router-interface-delete $DEFAULT_ROUTER port=$port_id - fi -done - -# We can now delete the default router and the default network. -neutron router-delete $DEFAULT_ROUTER -neutron net-delete $DEFAULT_NET - diff --git a/deployment_scripts/update_etcd_cluster.sh b/deployment_scripts/update_etcd_cluster.sh deleted file mode 100755 index fd1cdbe..0000000 --- a/deployment_scripts/update_etcd_cluster.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash -# Copyright 2015 Metaswitch Networks - -this_node_address=$(python get_node_ip.py `hostname`) -controller_node_addresses=$(python get_node_ips_by_role.py controller) - -for node_address in ${controller_node_addresses[@]} -do - initial_cluster+="${node_address}=http://${node_address}:2380," -done - -initial_cluster=${initial_cluster::-1} # remove trailing comma - -service etcd stop -rm -rf /var/lib/etcd/* -awk '/exec \/usr\/bin\/etcd/{while(getline && $0 != ""){}}1' /etc/init/etcd.conf > tmp -mv tmp /etc/init/etcd.conf -cat << EXEC_CMD >> /etc/init/etcd.conf -exec /usr/bin/etcd -name ${this_node_address} \\ - -advertise-client-urls "http://${this_node_address}:2379,http://${this_node_address}:4001" \\ - -listen-client-urls "http://0.0.0.0:2379,http://0.0.0.0:4001" \\ - -listen-peer-urls "http://0.0.0.0:2380" \\ - -initial-advertise-peer-urls "http://${this_node_address}:2380" \\ - -initial-cluster-token fuel-cluster-1 \\ - -initial-cluster ${initial_cluster} \\ - -initial-cluster-state new - -EXEC_CMD -service etcd start - -retry_count=0 -while [[ $retry_count < 5 ]]; do - etcdctl cluster-health - if [[ $? == 0 ]]; then - break - else - ((retry_count++)) - service etcd restart - sleep 2 - fi -done - diff --git a/deployment_tasks.yaml b/deployment_tasks.yaml new file mode 100644 index 0000000..ab809fe --- /dev/null +++ b/deployment_tasks.yaml @@ -0,0 +1,340 @@ +# Groups + +- id: calico-rrs + type: group + version: 2.1.0 + role: + - calico-rr + tasks: [hiera, globals, setup_repositories, tools, logging, netconfig, hosts, deploy_start] + requires: + - deploy_start + required_for: + - deploy_end + parameters: + strategy: + type: one_by_one + +- id: calico-etcds + type: group + version: 2.1.0 + role: + - calico-etcd + tasks: [hiera, globals, setup_repositories, tools, logging, netconfig, hosts, deploy_start] + requires: + - deploy_start + required_for: + - deploy_end + parameters: + strategy: + type: one_by_one + +# Plugin tasks + +- id: hiera_override + type: puppet + version: 2.1.0 + groups: ["/.*/"] + requires: + - hiera + required_for: + - globals + parameters: + puppet_manifest: puppet/manifests/hiera_override.pp + puppet_modules: puppet/modules:/etc/puppet/modules + timeout: 3600 + +- id: calico-private-gateway-check + groups: ["/.*/"] + version: 2.1.0 + requires: + - globals + required_for: + - deploy_end + - netconfig + - hosts + type: puppet + parameters: + timeout: 180 + puppet_manifest: puppet/manifests/private_gateway_check.pp + puppet_modules: puppet/modules:/etc/puppet/modules + +- id: calico-repo-setup + role: + - calico-rr + - calico-etcd + - primary-controller + - controller + - compute + version: 2.1.0 + requires: + - netconfig + - hosts + required_for: + - deploy_end + - openstack-network-start + type: puppet + parameters: + timeout: 180 + puppet_manifest: puppet/manifests/repo_setup.pp + puppet_modules: puppet/modules:/etc/puppet/modules + +- id: calico-rr + role: + - calico-rr + version: 2.1.0 + requires: + - netconfig + - hosts + - firewall + - calico-repo-setup + required_for: + - deploy_end + - openstack-network-start + condition: + yaql_exp: > + changedAny($.configuration, $.debug, $.network_metadata, $.network_scheme, $['fuel-plugin-calico']) + type: puppet + parameters: + timeout: 180 + puppet_manifest: puppet/manifests/role_rr.pp + puppet_modules: puppet/modules:/etc/puppet/modules + +- id: calico-etcd + role: + - calico-etcd + version: 2.1.0 + requires: + - netconfig + - hosts + - firewall + - calico-repo-setup + required_for: + - deploy_end + - openstack-network-start + condition: + yaql_exp: > + changedAny($.configuration, $.debug, $.network_metadata, $.network_scheme, $['fuel-plugin-calico']) + type: puppet + parameters: + timeout: 180 + puppet_manifest: puppet/manifests/role_etcd.pp + puppet_modules: puppet/modules:/etc/puppet/modules + +- id: calico-etcd-proxy + role: + - primary-controller + - controller + - compute + version: 2.1.0 + requires: + - netconfig + - hosts + - firewall + - calico-repo-setup + required_for: + - deploy_end + - openstack-network-start + cross-depends: + - name: primary-calico-etcd + role: ["/(primary-)?calico-etcd/"] + - name: calico-etcd + role: ["/(primary-)?calico-etcd/"] + condition: + yaql_exp: not ('calico-etcd' in $.roles) + type: puppet + parameters: + timeout: 180 + puppet_manifest: puppet/manifests/etcd_proxy.pp + puppet_modules: puppet/modules:/etc/puppet/modules + +- id: openstack-network-server-config + type: puppet + version: 2.1.0 + groups: + - primary-controller + - controller + requires: + - calico-repo-setup + - calico-etcd-proxy + - openstack-network-start + - openstack-network-common-config + required_for: + - openstack-network-end + cross-depends: + - name: /(primary-)?calico-rr/ + role: ["/(primary-)?calico-rr/"] + - name: /(primary-)?calico-etcd/ + role: ["/(primary-)?calico-etcd/"] + condition: + yaql_exp: > + changedAny($.quantum, $.configuration, $.quantum_settings, + $.get('database_vip'), $.network_metadata.vips, $.nova, + $.get('neutron_primary_controller_roles'), + $.get('neutron_compute_nodes'), $.get('region', 'RegionOne'), + $.get('use_ssl'), $.neutron_advanced_configuration, $.network_scheme) + refresh_on: + - neutron_plugin_ml2 + - neutron_config + - neutron_api_config + parameters: + puppet_manifest: puppet/manifests/neutron_server_config.pp + puppet_modules: puppet/modules:/etc/puppet/modules + timeout: 1800 + +- id: openstack-network-networks + type: puppet + version: 2.1.0 + groups: + - primary-controller + requires: + - openstack-network-start + - openstack-network-common-config + - openstack-network-server-config + required_for: + - openstack-network-end + condition: + yaql_exp: "changedAny($.access, $.quantum_settings, $.quantum)" + parameters: + puppet_manifest: puppet/manifests/neutron_networks.pp + puppet_modules: puppet/modules:/etc/puppet/modules + timeout: 1800 + +- id: calico-compute-bird + role: + - compute + version: 2.1.0 + requires: + - netconfig + - hosts + - firewall + - calico-repo-setup + required_for: + - deploy_end + - openstack-network-start + cross-depends: + - name: /(primary-)?calico-rr/ + role: ["/(primary-)?calico-rr/"] + condition: + yaql_exp: > + changedAny($.configuration, $.debug, $.network_metadata, $.network_scheme, $['fuel-plugin-calico']) + type: puppet + parameters: + timeout: 180 + puppet_manifest: puppet/manifests/compute_bird.pp + puppet_modules: puppet/modules:/etc/puppet/modules + +- id: openstack-network-compute-nova + type: puppet + version: 2.1.0 + groups: [compute] + requires: [openstack-network-start, calico-etcd-proxy] + required_for: [openstack-network-end] + condition: + yaql_exp: > + changedAny($.network_scheme, $.quantum, $.quantum_settings, $.nova, + $.network_metadata.vips, $.get('region'), $.get('use_ssl'), $['fuel-plugin-calico']) + parameters: + puppet_manifest: puppet/manifests/compute_neutron_nova.pp + puppet_modules: puppet/modules:/etc/puppet/modules + timeout: 1800 + +- id: calico-compute-metadata-api + type: puppet + version: 2.1.0 + groups: [compute] + requires: [openstack-network-end, calico-etcd-proxy, top-role-compute] + required_for: [enable_nova_compute_service] + condition: + yaql_exp: > + changedAny($.quantum, $.configuration, $.debug, + $.neutron_advanced_configuration, $['fuel-plugin-calico']) + parameters: + puppet_manifest: puppet/manifests/compute_metadata_api.pp + puppet_modules: puppet/modules:/etc/puppet/modules + timeout: 1800 + +- id: calico-compute-alt-gateway + type: puppet + version: 2.1.0 + groups: [compute] + requires: [openstack-network-end, calico-etcd-proxy, top-role-compute] + required_for: [enable_nova_compute_service, calico-compute-felix] + condition: + yaql_exp: > + changedAny($.quantum, $.configuration, + $.neutron_advanced_configuration, $['fuel-plugin-calico']) + parameters: + puppet_manifest: puppet/manifests/compute_alt_gateway.pp + puppet_modules: puppet/modules:/etc/puppet/modules + timeout: 1800 + +- id: calico-compute-felix + type: puppet + version: 2.1.0 + groups: [compute] + requires: [openstack-network-end, calico-etcd-proxy, top-role-compute] + required_for: [enable_nova_compute_service] + condition: + yaql_exp: > + changedAny($.quantum, $.configuration, $.debug, + $.neutron_advanced_configuration, $['fuel-plugin-calico']) + parameters: + puppet_manifest: puppet/manifests/compute_felix.pp + puppet_modules: puppet/modules:/etc/puppet/modules + timeout: 1800 + +- id: openstack-network-agents-dhcp + type: puppet + version: 2.1.0 + groups: [compute] + requires: [openstack-network-end, calico-etcd-proxy, calico-compute-felix, top-role-compute] + required_for: [enable_nova_compute_service] + condition: + yaql_exp: > + changedAny($.quantum, $.configuration, $.debug, + $.neutron_advanced_configuration, $['fuel-plugin-calico']) + refresh_on: [neutron_dhcp_agent_config] + parameters: + puppet_manifest: puppet/manifests/compute_dhcp_agent.pp + puppet_modules: puppet/modules:/etc/puppet/modules + timeout: 1800 + +# Disable Neutron tasks, not required for Calice setup + +- id: openstack-network-routers + groups: ["/.*/"] + version: 2.1.0 + type: skipped + +- id: primary-openstack-network-agents-dhcp + groups: ["/.*/"] + version: 2.1.0 + type: skipped +# Task with id:openstack-network-agents-dhcp was redefined above + +- id: primary-openstack-network-plugins-l2 + groups: ["/.*/"] + version: 2.1.0 + type: skipped +- id: openstack-network-plugins-l2 + groups: ["/.*/"] + version: 2.1.0 + type: skipped + +- id: primary-openstack-network-agents-l3 + groups: ["/.*/"] + version: 2.1.0 + type: skipped +- id: openstack-network-agents-l3 + groups: ["/.*/"] + version: 2.1.0 + type: skipped + +- id: primary-openstack-network-agents-metadata + groups: ["/.*/"] + version: 2.1.0 + type: skipped +- id: openstack-network-agents-metadata + groups: ["/.*/"] + version: 2.1.0 + type: skipped diff --git a/environment_config.yaml b/environment_config.yaml index 63aed59..a848ccc 100644 --- a/environment_config.yaml +++ b/environment_config.yaml @@ -1 +1,45 @@ -attributes: {} +attributes: + metadata: + label: Calico networking + description: Deploy OpenStack with Calico L3 fabric instead of Neutron L2 isolation + weight: 28400 + group: network + as_number: + value: '64512' + label: AS Number + description: AS number for BGP communication + weight: 20 + type: "text" + regex: + source: '^([1-9]|[0-9]{2,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-4])$' + error: "Invalid AS number" + enable_ipv4: + type: checkbox + weight: 60 + value: true + label: Enable IPv4 + description: Operate with bird4 BGP daemon + enable_ipv6: + type: checkbox + weight: 62 + value: false + label: Enable IPv6 + description: Operate with bird6 BGP daemon + restrictions: + - condition: "settings:fuel-plugin-calico.metadata.enabled == true" # disable, because in TODO + strict: false + enable_external_peering: + type: checkbox + weight: 70 + value: false + label: Allow external BGP peering + external_peers: + label: External BGP peers + description: One BGP peer per line in format 'name:as_number:ipaddr:optional_flags...' + weight: 71 + type: "textarea" + value: '' + restrictions: + - condition: "settings:fuel-plugin-calico.enable_external_peering.value != true" + strict: false + diff --git a/metadata.yaml b/metadata.yaml index 76381eb..f0e7917 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -1,15 +1,19 @@ # Plugin name -name: calico-fuel-plugin +name: fuel-plugin-calico # Human-readable name for your plugin title: Use Calico Virtual Networking # Plugin version -version: 2.0.0 +version: 3.0.1 # Description description: Layer 3 Virtual Networking for Highly Scalable Data Centers # Required fuel version -fuel_version: ['7.0'] +fuel_version: ['9.0','9.1'] # Plugin authors -authors: ['Emma Gordon'] +authors: + - Emma Gordon + - Alexander Didenko + - Oleksandr Martsyniuk + - Sergey Vasilenko # Plugin license licenses: [Apache License Version 2.0] # Plugin project homepage @@ -20,10 +24,16 @@ groups: ['network'] # The plugin is compatible with releases in the list releases: - os: ubuntu - version: 2015.1-7.0 - mode: ['ha', 'multinode'] + version: mitaka-9.0 + mode: ['ha'] + deployment_scripts_path: deployment_scripts/ + repository_path: repositories/ubuntu + - os: ubuntu + version: mitaka-9.1 + mode: ['ha'] deployment_scripts_path: deployment_scripts/ repository_path: repositories/ubuntu # Version of plugin package -package_version: '2.0.0' +package_version: '4.0.0' +is_hotpluggable: false diff --git a/node_roles.yaml b/node_roles.yaml new file mode 100644 index 0000000..9b5ccee --- /dev/null +++ b/node_roles.yaml @@ -0,0 +1,20 @@ +calico-rr: + name: Calico - RR + description: Calico route-reflector role + has_primary: false + limits: + min: 1 + recommended: 2 + public_ip_required: false + weight: 100 + conflicts: + - compute +calico-etcd: + name: Calico - etcd + description: Calico etcd instance. + has_primary: false + limits: + min: 1 + recommended: 3 + public_ip_required: false + weight: 100 diff --git a/pre_build_hook b/pre_build_hook deleted file mode 100644 index be74a7e..0000000 --- a/pre_build_hook +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -# Add here any the actions which are required before plugin build -# like packages building, packages downloading from mirrors and so on. -# The script should return 0 if there were no errors. - -#!/bin/bash -set -eux -ROOT="$(dirname `readlink -f $0`)" -MODULES="${ROOT}"/deployment_scripts/puppet/modules -mkdir -p "${MODULES}" -REPO_PATH='https://github.com/openstack/fuel-library/tarball/f43d885914d74fbd062096763222f350f47480e1' -RPM_REPO="${ROOT}"/repositories/centos/ -DEB_REPO="${ROOT}"/repositories/ubuntu/ - -wget -qO- "${REPO_PATH}" | \ - tar -C "${MODULES}" --strip-components=3 -zxvf - \ - openstack-fuel-library-f43d885/deployment/puppet/{inifile,stdlib} diff --git a/pre_install.sh b/pre_install.sh new file mode 100644 index 0000000..1aba92e --- /dev/null +++ b/pre_install.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +PWD=`pwd` + +FUEL_VERSION=`rpm -q --info fuel | tr -s \[:space:\] | grep 'Version :' | awk -F': ' '{print $2}'` +if [ $FUEL_VERSION == '9.0.0' ] ; then +# Implement minor patch to l23network (included into 9.1, but not present in 9.0) +# For additional information see Openstack Bug #1590735 +# or Change-Id: I89ef5630ab2dfd373b8cd4b7db481278c659db75 + +cd /etc/puppet/modules/l23network +patch -N -p4 < (developer) + Sergey Vasilenko Other contributors: - Neil Jerram (developer, reviewer) + Alexander Didenko + Oleksandr Martsyniuk Work Items ---------- -* Integrate Calico with Fuel 7.0. +* Integrate Calico with Fuel 9.0. * Update the Calico plugin. @@ -115,7 +117,7 @@ Work Items Dependencies ============ -* Fuel 7.0. +* Fuel 9.0. Testing ======= @@ -142,7 +144,4 @@ References * Calico Documentation - http://docs.projectcalico.org/en/latest/index.html -* Subscribe to the Calico Technical Mailing List - - http://lists.projectcalico.org/listinfo/calico-tech - * Calico IRC - freenode IRC: #calico diff --git a/tasks.yaml b/tasks.yaml index 6e628c7..e69de29 100644 --- a/tasks.yaml +++ b/tasks.yaml @@ -1,33 +0,0 @@ -# Copyright 2015 Metaswitch Networks - -# Install/configure calico on the controller after cluster deployment -# but before starting the BGP Route Reflector. -- role: ['controller', 'primary-controller'] - stage: post_deployment/50 - type: shell - parameters: - cmd: ./calico_controller.sh - timeout: 600 - -- role: ['controller', 'primary-controller'] - stage: post_deployment/100 - type: shell - parameters: - cmd: ./calico_route_reflector.sh - timeout: 60 - -# Remove default OpenStack network configuration which doesn't work with Calico. -#- role: ['primary-controller'] -# stage: post_deployment/150 -# type: shell -# parameters: -# cmd: ./remove_default_networks.sh -# timeout: 60 - -# Install/configure calico on the compute nodes after cluster deployment. -- role: ['compute'] - stage: post_deployment - type: shell - parameters: - cmd: ./calico_compute.sh - timeout: 600