Introduced master node management strategy

* Only one Git repository is allowed to manage Fuel master node
* Repo SQL model extended with flag which determines wither a particular
  repo manages Fuel mater node
* Master config mapping moved to a separate section

Change-Id: I7137393a5a42bb57cc14ceb738b18e37251e9368
This commit is contained in:
Dmitry Ukov 2016-09-27 10:44:55 +03:00
parent 5a11df2194
commit 40e1ede7b9
7 changed files with 117 additions and 17 deletions

View File

@ -52,7 +52,6 @@ class OpenStackConfigPipeline(BasePipeline):
GitRepo.checkout(repo)
repo_path = os.path.join(const.REPOS_DIR, repo.repo_name)
resource_mapping = ExternalGit.ext_settings['resource_mapping']
resource_mapping.pop('master_config', {})
exts_list = utils.get_file_exts_list(resource_mapping)
global_config = utils.get_config_hash(repo_path,
@ -108,17 +107,17 @@ class OpenStackConfigPipeline(BasePipeline):
repo = GitRepo.get_by_cluster_id(cluster.id)
if not repo:
return data
GitRepo.checkout(repo)
repo_path = os.path.join(const.REPOS_DIR, repo.repo_name)
resource_mapping = ExternalGit.ext_settings['resource_mapping']
master_config_mapping = resource_mapping.pop('master_config', {})
master_config = utils.get_config_hash(
repo_path,
{'master_config': master_config_mapping},
exts=['yaml']
)
if repo.manage_master:
GitRepo.checkout(repo)
repo_path = os.path.join(const.REPOS_DIR, repo.repo_name)
resource_mapping = ExternalGit.ext_settings['master_mapping']
master_config = utils.get_config_hash(
repo_path,
{'master_config': resource_mapping.get('master_config', {})},
exts=['yaml']
)
data['master_config'] = master_config
data['master_config'] = master_config
return data

View File

@ -31,7 +31,8 @@ class GitRepoList(lister.Lister, command.Command):
'repo_name',
'env_id',
'git_url',
'ref'
'ref',
'manage_master',
)
def get_parser(self, prog_name):
@ -54,11 +55,13 @@ class AddRepo(command.Command):
'repo_name',
'env_id',
'git_url',
'ref'
'ref',
'manage_master',
)
def get_parser(self, prog_name):
parser = super(AddRepo, self).get_parser(prog_name)
mm = parser.add_mutually_exclusive_group(required=False)
parser.add_argument('--env',
type=int,
help='ID of environment to configure.',
@ -87,6 +90,19 @@ class AddRepo(command.Command):
type=str,
help='Path to private key file for accessing repo',
required=False)
mm.add_argument('--manage-master',
dest='manage_master',
help='Enable Fuel master management from this repo',
action='store_true',
required=False)
mm.add_argument('--no-manage-master',
dest='manage_master',
help='Disable Fuel master management from this repo',
action='store_false',
required=False)
parser.set_defaults(manage_master=False)
return parser
def take_action(self, parsed_args):
@ -95,6 +111,7 @@ class AddRepo(command.Command):
'env_id': parsed_args.env,
'git_url': parsed_args.url,
'ref': parsed_args.ref,
'manage_master': parsed_args.manage_master,
}
if parsed_args.key:
@ -142,11 +159,13 @@ class UpdateRepo(command.Command):
'id',
'repo_name',
'git_url',
'ref'
'ref',
'manage_master',
)
def get_parser(self, prog_name):
parser = super(UpdateRepo, self).get_parser(prog_name)
mm = parser.add_mutually_exclusive_group(required=False)
parser.add_argument('--repo',
type=int,
help='Repo ID to update',
@ -175,6 +194,19 @@ class UpdateRepo(command.Command):
type=str,
help='Path to private key file for accessing repo',
required=False)
mm.add_argument('--manage-master',
dest='manage_master',
help='Enable Fuel master management from this repo',
action='store_true',
required=False)
mm.add_argument('--no-manage-master',
dest='manage_master',
help='Disable Fuel master management from this repo',
action='store_false',
required=False)
parser.set_defaults(manage_master=False)
return parser
def take_action(self, parsed_args):
@ -182,11 +214,12 @@ class UpdateRepo(command.Command):
'name': 'repo_name',
'url': 'git_url',
'ref': 'ref',
'manage_master': 'manage_master',
}
data = {}
for param, value in parsed_args.__dict__.items():
if value and param in param_mapping.keys():
if value is not None and param in param_mapping.keys():
data[param_mapping[param]] = value
repos = APIClient.get_request('/clusters/git-repos/')
env = [repo['env_id'] for repo in repos

View File

@ -24,6 +24,7 @@ from nailgun.api.v1.validators import base
from nailgun import errors
from nailgun import objects
REPOS_DIR = '/var/lib/fuel_repos'
@ -37,8 +38,28 @@ class GitRepoValidator(base.BasicValidator):
)
@classmethod
def validate_update(self, data, instance):
def _validate_master_mgmt(self, data, instance=None):
d = self.validate_json(data)
if instance:
repo_id = instance.id
else:
repo_id = d.get('id', None)
if d.get('manage_master', False):
for repo in GitRepoCollection.all():
if repo.manage_master and repo_id != repo.id:
raise errors.InvalidData(
("Repo {} already marked for Fuel Master management. "
"Disable it first".format(repo.id)),
log_message=True)
return d
@classmethod
def validate(self, data):
return self._validate_master_mgmt(data)
@classmethod
def validate_update(self, data, instance):
d = self._validate_master_mgmt(data, instance)
env_id = d.get('env_id')
if env_id:
cluster = objects.Cluster.get_by_uid(env_id)

View File

@ -0,0 +1,43 @@
# 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.
"""Manage fuel node flag
Revision ID: adb78f70605d
Revises: d59114c46ac4
Create Date: 2016-09-26 10:10:37.779555
"""
# revision identifiers, used by Alembic.
revision = 'adb78f70605d'
down_revision = 'd59114c46ac4'
branch_labels = None
depends_on = None
import sqlalchemy as sa
from alembic import context
from alembic import op
def upgrade():
table_prefix = context.config.get_main_option('table_prefix')
op.add_column(
table_prefix + 'repos',
sa.Column('manage_master', sa.Boolean(), nullable=True)
)
def downgrade():
table_prefix = context.config.get_main_option('table_prefix')
op.drop_column(table_prefix + 'repos', 'manage_master')

View File

@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from sqlalchemy import Boolean
from sqlalchemy import Column
from sqlalchemy import Integer
from sqlalchemy import String
@ -28,3 +29,4 @@ class GitRepo(Base):
ref = Column(String(255), default='', server_default='', nullable=False)
user_key = Column(String(255), default='', server_default='',
nullable=False)
manage_master = Column(Boolean(), nullable=False)

View File

@ -38,7 +38,8 @@ class GitRepoSerializer(BasicSerializer):
"env_id",
"git_url",
"ref",
"user_key"
"user_key",
"manage_master"
)

View File

@ -62,6 +62,7 @@ resource_mapping:
nova_paste_api_ini:
alias: nova-api-paste.ini
path: /etc/nova/api-paste.ini
master_mapping:
master_config:
alias: master_config.yaml
path: ""