summaryrefslogtreecommitdiffstats
path: root/lib/python/apex/deploy_settings.py
blob: 3133d7f87a053d3ded8ea63fefa314f0efab99df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

@media only all and (prefers-color-scheme: dark) {
.highlight .hll { background-color: #49483e }
.highlight .c { color: #75715e } /* Comment */
.highlight .err { color: #960050; background-color: #1e0010 } /* Error */
.highlight .k { color: #66d9ef } /* Keyword */
.highlight .l { color: #ae81ff } /* Literal */
.highlight .n { color: #f8f8f2 } /* Name */
.highlight .o { color: #f92672 } /* Operator */
.highlight .p { color: #f8f8f2 } /* Punctuation */
.highlight .ch { color: #75715e } /* Comment.Hashbang */
.highlight .cm { color: #75715e } /* Comment.Multiline */
.highlight .cp { color: #75715e } /* Comment.Preproc */
.highlight .cpf { color: #75715e } /* Comment.PreprocFile */
.highlight .c1 { color: #75715e } /* Comment.Single */
.highlight .cs { color: #75715e } /* Comment.Special */
.highlight .gd { color: #f92672 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gi { color: #a6e22e } /* Generic.Inserted */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #75715e } /* Generic.Subheading */
.highlight .kc { color: #66d9ef } /* Keyword.Constant */
.highlight .kd { color: #66d9ef } /* Keyword.Declaration */
.highlight .kn { color: #f92672 } /* Keyword.Namespace */
.highlight .kp { color: #66d9ef } /* Keyword.Pseudo */
.highlight .kr { color: #66d9ef } /* Keyword.Reserved */
.highlight .kt { color: #66d9ef } /* Keyword.Type */
.highlight .ld { color: #e6db74 } /* Literal.Date */
.highlight .m { color: #ae81ff } /* Literal.Number */
.highlight .s { color: #e6db74 } /* Literal.String */
.highlight .na { color: #a6e22e } /* Name.Attribute */
.highlight .nb { color: #f8f8f2 } /* Name.Builtin */
.highlight .nc { color: #a6e22e } /* Name.Class */
.highlight .no { color: #66d9ef } /* Name.Constant */
.highlight .nd { color: #a6e22e } /* Name.Decorator */
.highlight .ni { color: #f8f8f2 } /* Name.Entity */
.highlight .ne { color: #a6e22e } /* Name.Exception */
.highlight .nf { color: #a6e22e } /* Name.Function */
.highlight .nl { color: #f8f8f2 } /* Name.Label */
.highlight .nn { color: #f8f8f2 } /* Name.Namespace */
.highlight .nx { color: #a6e22e } /* Name.Other */
.highlight .py { color: #f8f8f2 } /* Name.Property */
.highlight .nt { color: #f92672 } /* Name.Tag */
.highlight .nv { color: #f8f8f2 } /* Name.Variable */
.highlight .ow { color: #f92672 } /* Operator.Word */
.highlight .w { color: #f8f8f2 } /* Text.Whitespace */
.highlight .mb { color: #ae81ff } /* Literal.Number.Bin */
.highlight .mf { color: #ae81ff } /* Literal.Number.Float */
.highlight .mh { color: #ae81ff } /* Literal.Number.Hex */
.highlight .mi { color: #ae81ff } /* Literal.Number.Integer */
.highlight .mo { color: #ae81ff } /* Literal.Number.Oct */
.highlight .sa { color: #e6db74 } /* Literal.String.Affix */
.highlight .sb { color: #e6db74 } /* Literal.String.Backtick */
.highlight .sc { color: #e6db74 } /* Literal.String.Char */
.highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */
.highlight .sd { color: #e6db74 } /* Literal.String.Doc */
.highlight .s2 { color: #e6db74 } /* Literal.String.Double */
.highlight .se { color: #ae81ff } /* Literal.String.Escape */
.highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */
.highlight .si { color: #e6db74 } /* Literal.String.Interpol */
.highlight .sx { color: #e6db74 } /* Literal.String.Other */
.highlight .sr { color: #e6db74 } /* Literal.String.Regex */
.highlight .s1 { color: #e6db74 } /* Literal.String.Single */
.highlight .ss { color: #e6db74 } /* Literal.String.Symbol */
.highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #a6e22e } /* Name.Function.Magic */
.highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */
.highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */
.highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */
.highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */
.highlight .il { color: #ae81ff }
##############################################################################
# Copyright (c) 2016 Michael Chapman (michapma@redhat.com) and others.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Apache License, Version 2.0
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################


import yaml
import logging

from .common import utils

REQ_DEPLOY_SETTINGS = ['sdn_controller',
                       'odl_version',
                       'sdn_l3',
                       'tacker',
                       'congress',
                       'dataplane',
                       'sfc',
                       'vpn',
                       'vpp',
                       'ceph']

OPT_DEPLOY_SETTINGS = ['performance', 'vsperf', 'ceph_device']

VALID_ROLES = ['Controller', 'Compute', 'ObjectStorage']
VALID_PERF_OPTS = ['kernel', 'nova', 'vpp']
VALID_DATAPLANES = ['ovs', 'ovs_dpdk', 'fdio']


class DeploySettings(dict):
    """
    This class parses a APEX deploy settings yaml file into an object

    Currently the parsed object is dumped into a bash global definition file
    for deploy.sh consumption. This object will later be used directly as
    deployment script move to python.
    """
    def __init__(self, filename):
        init_dict = {}
        if isinstance(filename, str):
            with open(filename, 'r') as deploy_settings_file:
                init_dict = yaml.safe_load(deploy_settings_file)
        else:
            # assume input is a dict to build from
            init_dict = filename

        super().__init__(init_dict)
        self._validate_settings()

    def _validate_settings(self):
        """
        Validates the deploy settings file provided

        DeploySettingsException will be raised if validation fails.
        """

        if 'deploy_options' not in self:
            raise DeploySettingsException("No deploy options provided in"
                                          " deploy settings file")
        if 'global_params' not in self:
            raise DeploySettingsException("No global options provided in"
                                          " deploy settings file")

        deploy_options = self['deploy_options']
        if not isinstance(deploy_options, dict):
            raise DeploySettingsException("deploy_options should be a list")

        for setting, value in deploy_options.items():
            if setting not in REQ_DEPLOY_SETTINGS + OPT_DEPLOY_SETTINGS:
                raise DeploySettingsException("Invalid deploy_option {} "
                                              "specified".format(setting))
            if setting == 'dataplane':
                if value not in VALID_DATAPLANES:
                    planes = ' '.join(VALID_DATAPLANES)
                    raise DeploySettingsException(
                        "Invalid dataplane {} specified. Valid dataplanes:"
                        " {}".format(value, planes))

        for req_set in REQ_DEPLOY_SETTINGS:
            if req_set not in deploy_options:
                if req_set == 'dataplane':
                    self['deploy_options'][req_set] = 'ovs'
                elif req_set == 'ceph':
                    self['deploy_options'][req_set] = True
                else:
                    self['deploy_options'][req_set] = False

        if 'performance' in deploy_options:
            if not isinstance(deploy_options['performance'], dict):
                raise DeploySettingsException("Performance deploy_option"
                                              "must be a dictionary.")
            for role, role_perf_sets in deploy_options['performance'].items():
                if role not in VALID_ROLES:
                    raise DeploySettingsException("Performance role {}"
                                                  "is not valid, choose"
                                                  "from {}".format(
                                                      role,
                                                      " ".join(VALID_ROLES)
                                                  ))

                for key in role_perf_sets:
                    if key not in VALID_PERF_OPTS:
                        raise DeploySettingsException("Performance option {} "
                                                      "is not valid, choose"
                                                      "from {}".format(
                                                          key,
                                                          " ".join(
                                                              VALID_PERF_OPTS)
                                                      ))

    def _dump_performance(self):
        """
        Creates performance settings string for bash consumption.

        Output will be in the form of a list that can be iterated over in
        bash, with each string being the direct input to the performance
        setting script in the form <role> <category> <key> <value> to
        facilitate modification of the correct image.
        """
        bash_str = 'performance_options=(\n'
        deploy_options = self['deploy_options']
        for role, settings in deploy_options['performance'].items():
            for category, options in settings.items():
                for key, value in options.items():
                    bash_str += "\"{} {} {} {}\"\n".format(role,
                                                           category,
                                                           key,
                                                           value)
        bash_str += ')\n'
        bash_str += '\n'
        bash_str += 'performance_roles=(\n'
        for role in self['deploy_options']['performance']:
            bash_str += role + '\n'
        bash_str += ')\n'
        bash_str += '\n'

        return bash_str

    def _dump_deploy_options_array(self):
        """
        Creates deploy settings array in bash syntax.
        """
        bash_str = ''
        for key, value in self['deploy_options'].items():
            if not isinstance(value, bool):
                bash_str += "deploy_options_array[{}]=\"{}\"\n".format(key,
                                                                       value)
            else:
                bash_str += "deploy_options_array[{}]={}\n".format(key,
                                                                   value)
        return bash_str

    def dump_bash(self, path=None):
        """
        Prints settings for bash consumption.

        If optional path is provided, bash string will be written to the file
        instead of stdout.
        """
        bash_str = ''
        for key, value in self['global_params'].items():
            bash_str += "{}={}\n".format(key, value)
        if 'performance' in self['deploy_options']:
            bash_str += self._dump_performance()
        bash_str += self._dump_deploy_options_array()
        utils.write_str(bash_str, path)


class DeploySettingsException(Exception):
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return self.value