crowbar/crowbar-openstack

View on GitHub
crowbar_framework/app/models/designate_service.rb

Summary

Maintainability
B
4 hrs
Test Coverage
# Copyright 2018, SUSE LINUX GmbH
#
# 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 DesignateService < OpenstackServiceObject
  def initialize(thelogger = nil)
    super(thelogger)
    @bc_name = "designate"
  end

  # Turn off multi proposal support till it really works and people ask for it
  def self.allow_multiple_proposals?
    false
  end

  def proposal_dependencies(role)
    answer = []
    deps = ["database", "rabbitmq", "keystone"]
    deps.each do |dep|
      answer << {
        "barclamp" => dep,
        "inst" => role.default_attributes[@bc_name]["#{dep}_instance"]
      }
    end
    answer
  end

  class << self
    def role_constraints
      {
        "designate-server" => {
          "unique" => false,
          "count" => 1,
          "cluster" => true,
          "admin" => false,
          "exclude_platform" => {
            "suse" => "< 12.4",
            "windows" => "/.*/"
          }
        },
        "designate-worker" => {
          "unique" => false,
          "count" => 1,
          "cluster" => true,
          "admin" => false,
          "exclude_platform" => {
            "suse" => "< 12.4",
            "windows" => "/.*/"
          }
        }
      }
    end
  end

  def create_proposal
    @logger.debug("Designate create_proposal: entering")
    base = super

    nodes = NodeObject.all
    nodes.delete_if { |n| n.nil? || n.admin? }
    if nodes.size >= 1
      controller = nodes.find { |n| n.intended_role == "controller" } || nodes.first
      base["deployment"][@bc_name]["elements"] = {
        "designate-server" => [controller[:fqdn]],
        "designate-worker" => [controller[:fqdn]]
      }
      base["attributes"][@bc_name]["resource_email"] = "crowbar@#{controller[:domain]}"
    end

    base["attributes"][@bc_name]["database_instance"] = find_dep_proposal("database")
    base["attributes"][@bc_name]["rabbitmq_instance"] = find_dep_proposal("rabbitmq")
    base["attributes"][@bc_name]["keystone_instance"] = find_dep_proposal("keystone")

    base["attributes"][@bc_name]["service_password"] = random_password
    base["attributes"][@bc_name]["memcache_secret_key"] = random_password
    base["attributes"][@bc_name][:db][:password] = random_password

    @logger.debug("Designate create_proposal: exiting")
    base
  end

  def validate_proposal_after_save(proposal)
    validate_one_for_role proposal, "designate-server"
    validate_one_for_role proposal, "designate-worker"

    designate_bc = proposal["attributes"][@bc_name]
    email = designate_bc["resource_email"]
    if email !~ /\w@[^.]+\.\w+/
      validation_error I18n.t(
        "barclamp.#{@bc_name}.validation.invalid_email_address",
        email: email
      )
    end

    # Make sure dns-server role is applied to at least one non-admin node
    dns_server_nodes = NodeObject.find("roles:dns-server")
    dns_server_nodes.delete_if { |n| n.nil? || n.admin? }
    if dns_server_nodes.empty?
      validation_error I18n.t(
        "barclamp.#{@bc_name}.validation.non_admin_dns_nodes_not_found"
      )
    end

    # All designate-worker nodes should have dns-server role too. This is
    # assuming that designate-working is deployed on all the controller nodes.
    designate_worker_nodes = NodeObject.find("roles:designate-worker")
    designate_worker_nodes.each do |node|
      next if node.roles.include?("dns-server")
      @logger.warn(
        "Node #{node.name} does not have dns-server role. All "\
        "designate-worker node(s) should have dns-server role too."
      )
    end

    super
  end

  def apply_role_pre_chef_call(old_role, role, all_nodes)
    @logger.debug("Designate apply_role_pre_chef_call: entering #{all_nodes.inspect}")
    return if all_nodes.empty?

    vip_networks = ["admin", "public"]

    server_elements, server_nodes, ha_enabled = role_expand_elements(role, "designate-server")
    reset_sync_marks_on_clusters_founders(server_elements)
    Openstack::HA.set_controller_role(server_nodes) if ha_enabled

    role.save if prepare_role_for_ha_with_haproxy(role, ["designate", "ha", "enabled"],
                                                  ha_enabled, server_elements, vip_networks)

    net_svc = NetworkService.new @logger
    # All nodes must have a public IP, even if part of a cluster; otherwise
    # the VIP can't be moved to the nodes
    server_nodes.each do |n|
      net_svc.allocate_ip "default", "public", "host", n
    end

    allocate_virtual_ips_for_any_cluster_in_networks(server_elements, vip_networks)

    @logger.debug("Designate apply_role_pre_chef_call: leaving")
  end
end