Merge "Always send versioned paths to manifests/repos"

This commit is contained in:
Jenkins 2014-11-26 12:55:11 +00:00 committed by Gerrit Code Review
commit bf9ddb9f9d
11 changed files with 184 additions and 58 deletions

View File

@ -35,6 +35,7 @@ class ReleaseValidator(BasicValidator):
"Invalid network data: {0}".format(network),
log_message=True
)
if "orchestrator_data" in d:
if not isinstance(d["orchestrator_data"], dict):
raise errors.InvalidData(
@ -68,6 +69,11 @@ class ReleaseValidator(BasicValidator):
"No release operating system specified",
log_message=True
)
if "orchestrator_data" not in d:
raise errors.InvalidData(
'No orchestrator_data specified', log_message=True
)
if db().query(Release).filter_by(
name=d["name"],
version=d["version"]

View File

@ -106,8 +106,20 @@ def upload_fixture(fileobj, loader=None):
except Exception:
break
new_obj = obj['model']()
# NOTE(ikalnitsly):
# In order to add a release to Nailgun we have to fill two tables:
# releases and release_orchestrator_data. By using former fixture
# approach we can't do it, since the fixture is bond to only one
# database model and can't deal with additional logic. Therefore
# we need to use Nailgun's objects which know how to handle it.
#
# TODO(ikalnitsky):
# Rewrite fixture logic - it must be simple and obvious.
if obj['model'] is objects.Release.model:
objects.Release.create(obj['fields'])
continue
new_obj = obj['model']()
fk_fields = {}
for field, value in obj["fields"].iteritems():
f = getattr(obj['model'], field)

View File

@ -1234,6 +1234,11 @@
uri: "http://{{settings.MASTER_IP}}:8080/targetimages/centos_65_x86_64-boot.img.gz"
format: "ext2"
container: "gzip"
orchestrator_data:
puppet_manifests_source: "rsync://{MASTER_IP}:/puppet/{OPENSTACK_VERSION}/manifests/"
puppet_modules_source: "rsync://{MASTER_IP}:/puppet/{OPENSTACK_VERSION}/modules/"
repo_metadata:
"{OPENSTACK_VERSION}": "http://{MASTER_IP}:8080/{OPENSTACK_VERSION}/centos/x86_64"
- pk: 2
extend: *base_release
fields:
@ -1257,3 +1262,8 @@
uri: "http://{{settings.MASTER_IP}}:8080/targetimages/ubuntu_1204_amd64-boot.img.gz"
format: "ext2"
container: "gzip"
orchestrator_data:
puppet_manifests_source: "rsync://{MASTER_IP}:/puppet/{OPENSTACK_VERSION}/manifests/"
puppet_modules_source: "rsync://{MASTER_IP}:/puppet/{OPENSTACK_VERSION}/modules/"
repo_metadata:
"{OPENSTACK_VERSION}": "http://{MASTER_IP}:8080/{OPENSTACK_VERSION}/ubuntu/x86_64 precise main"

View File

@ -24,7 +24,7 @@ from sqlalchemy import not_
from nailgun import consts
from nailgun.objects.serializers.release import ReleaseSerializer
from nailgun.objects.serializers import release as release_serializer
from nailgun.db import db
@ -43,6 +43,9 @@ class ReleaseOrchestratorData(NailgunObject):
#: SQLAlchemy model
model = models.ReleaseOrchestratorData
#: Serializer for ReleaseOrchestratorData
serializer = release_serializer.ReleaseOrchestratorDataSerializer
#: JSON schema
schema = {
"$schema": "http://json-schema.org/draft-04/schema#",
@ -84,13 +87,14 @@ class ReleaseOrchestratorData(NailgunObject):
release = Release.get_by_uid(rendered_data['release_id'])
context = {
'MASTER_IP': settings.MASTER_IP,
'OPENSTACK_VERSION': release.version,
}
'OPENSTACK_VERSION': release.version}
# render all the paths
repo_metadata = {}
for key, value in six.iteritems(rendered_data['repo_metadata']):
rendered_data['repo_metadata'][key] = \
cls.render_path(value, context)
formatted_key = cls.render_path(key, context)
repo_metadata[formatted_key] = cls.render_path(value, context)
rendered_data['repo_metadata'] = repo_metadata
rendered_data['puppet_manifests_source'] = \
cls.render_path(rendered_data.get(
@ -115,7 +119,7 @@ class Release(NailgunObject):
model = models.Release
#: Serializer for Release
serializer = ReleaseSerializer
serializer = release_serializer.ReleaseSerializer
#: Release JSON schema
schema = {
@ -220,41 +224,16 @@ class Release(NailgunObject):
@classmethod
def update_orchestrator_data(cls, instance, orchestrator_data):
for k in ["id", "release_id"]:
orchestrator_data.pop(k, None)
if orchestrator_data:
if instance.orchestrator_data:
ReleaseOrchestratorData.update(
instance.orchestrator_data, orchestrator_data)
else:
orchestrator_data["release_id"] = instance.id
ReleaseOrchestratorData.create(orchestrator_data)
orchestrator_data.pop("id", None)
orchestrator_data["release_id"] = instance.id
ReleaseOrchestratorData.update(
instance.orchestrator_data, orchestrator_data)
@classmethod
def get_orchestrator_data_dict(cls, instance):
os = instance.operating_system.lower()
default_orchestrator_data = {
"repo_metadata": {
"nailgun":
settings.DEFAULT_REPO[os].format(
MASTER_IP=settings.MASTER_IP),
},
"puppet_modules_source":
settings.DEFAULT_PUPPET['modules'].format(
MASTER_IP=settings.MASTER_IP),
"puppet_manifests_source":
settings.DEFAULT_PUPPET['manifests'].format(
MASTER_IP=settings.MASTER_IP),
}
return {
"repo_metadata":
instance.orchestrator_data.repo_metadata,
"puppet_modules_source":
instance.orchestrator_data.puppet_modules_source,
"puppet_manifests_source":
instance.orchestrator_data.puppet_manifests_source
} if instance.orchestrator_data else default_orchestrator_data
data = instance.orchestrator_data
return ReleaseOrchestratorData.serializer.serialize(data)
@classmethod
def is_deployable(cls, instance):

View File

@ -62,13 +62,6 @@ RABBITMQ:
fake: "0"
hostname: "127.0.0.1"
DEFAULT_PUPPET:
modules: "rsync://{MASTER_IP}:/puppet/modules/"
manifests: "rsync://{MASTER_IP}:/puppet/manifests/"
DEFAULT_REPO:
centos: "http://{MASTER_IP}:8080/centos/x86_64"
ubuntu: "http://{MASTER_IP}:8080/ubuntu/x86_64 precise main"
PLUGINS_PATH: '/var/www/nailgun/plugins'
PLUGINS_SLAVES_SCRIPTS_PATH: '/etc/fuel/plugins/{plugin_name}/'
PLUGINS_REPO_URL: 'http://{master_ip}:8080/plugins/{plugin_name}/'

View File

@ -134,6 +134,7 @@ class Environment(object):
'attributes_metadata': self.get_default_attributes_metadata(),
'volumes_metadata': self.get_default_volumes_metadata(),
'roles_metadata': self.get_default_roles_metadata(),
'orchestrator_data': self.get_default_orchestrator_data(),
}
if kwargs:
release_data.update(kwargs)
@ -469,6 +470,21 @@ class Environment(object):
sample_plugin.update(kwargs)
return sample_plugin
def get_default_orchestrator_data(self, **kwargs):
orchestrator_data = {
'puppet_manifests_source':
'rsync://127.0.0.1:/puppet/2014.2-6.0/manifests/',
'puppet_modules_source':
'rsync://127.0.0.1:/puppet/2014.2-6.0/modules/',
'repo_metadata': {
'2014.2-6.0': 'http://127.0.0.1:8080/2014.2-6.0/centos/x86_64'
}
}
orchestrator_data.update(kwargs)
return orchestrator_data
def upload_fixtures(self, fxtr_names):
for fxtr_path in self.fxtr_paths_by_names(fxtr_names):
with open(fxtr_path, "r") as fxtr_file:

View File

@ -1529,16 +1529,16 @@ class TestRepoAndPuppetDataSerialization(OrchestratorSerializerTestBase):
self.assertEqual(
fact['repo_metadata'],
{
'nailgun': 'http://127.0.0.1:8080/centos/x86_64'
'2014.2-6.0': 'http://127.0.0.1:8080/2014.2-6.0/centos/x86_64'
}
)
self.assertEqual(
fact['puppet_modules_source'],
'rsync://127.0.0.1:/puppet/modules/'
'rsync://127.0.0.1:/puppet/2014.2-6.0/modules/'
)
self.assertEqual(
fact['puppet_manifests_source'],
'rsync://127.0.0.1:/puppet/manifests/'
'rsync://127.0.0.1:/puppet/2014.2-6.0/manifests/'
)
def test_orch_data_w_replaced_deployment_info(self):

View File

@ -33,8 +33,10 @@ class TestPlugin(base.BaseTestCase):
self.plugin = Plugin.create(self.plugin_metadata)
self.env.create(
cluster_kwargs={'mode': 'multinode'},
release_kwargs={'version': '2014.2-6.0',
'operating_system': 'Ubuntu'})
release_kwargs={
'version': '2014.2-6.0',
'operating_system': 'Ubuntu',
'orchestrator_data': self.env.get_default_orchestrator_data()})
self.cluster = self.env.clusters[0]
self.attr_plugin = attr_plugin.ClusterAttributesPlugin(self.plugin)
self.env_config = self.env.get_default_plugin_env_config()

View File

@ -687,7 +687,8 @@ class TestReleaseOrchestratorData(BaseIntegrationTest):
self.data = {
'release_id': self.release.id,
'repo_metadata': {
'5': 'http://10.20.0.2:8080/{OPENSTACK_VERSION}/centos/x86_64',
'{OPENSTACK_VERSION}':
'http://10.20.0.2:8080/{OPENSTACK_VERSION}/centos/x86_64',
},
'puppet_manifests_source': 'rsync://10.20.0.2:/puppet/modules/',
'puppet_modules_source': 'rsync://10.20.0.2:/puppet/manifests/',
@ -695,7 +696,8 @@ class TestReleaseOrchestratorData(BaseIntegrationTest):
instance = objects.ReleaseOrchestratorData.create(self.data)
self.assertEqual(instance.repo_metadata, {
'5': 'http://10.20.0.2:8080/{0}/centos/x86_64'.format(
self.release.version:
'http://10.20.0.2:8080/{0}/centos/x86_64'.format(
self.release.version)})
self.assertEqual(
instance.puppet_manifests_source,

View File

@ -36,7 +36,9 @@ class TestHandlers(BaseIntegrationTest):
params=jsonutils.dumps({
'name': 'Another test release',
'version': '1.0',
'operating_system': 'CentOS'
'operating_system': 'CentOS',
'orchestrator_data':
self.env.get_default_orchestrator_data(),
}),
headers=self.default_headers
)
@ -80,7 +82,9 @@ class TestHandlers(BaseIntegrationTest):
}
]
}
}
},
'orchestrator_data':
self.env.get_default_orchestrator_data(),
}),
headers=self.default_headers
)
@ -109,7 +113,9 @@ class TestHandlers(BaseIntegrationTest):
}
]
}
}
},
'orchestrator_data':
self.env.get_default_orchestrator_data()
}),
headers=self.default_headers,
expect_errors=True
@ -161,7 +167,9 @@ class TestHandlers(BaseIntegrationTest):
}
]
}
}
},
'orchestrator_data':
self.env.get_default_orchestrator_data()
}),
headers=self.default_headers
)
@ -190,7 +198,9 @@ class TestHandlers(BaseIntegrationTest):
}
]
}
}
},
'orchestrator_data':
self.env.get_default_orchestrator_data(),
}),
headers=self.default_headers,
expect_errors=True

View File

@ -0,0 +1,96 @@
# Copyright 2014 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.
from nailgun.openstack.common import jsonutils
from nailgun.api.v1.validators.release import ReleaseValidator
from nailgun.errors import errors
from nailgun.test.base import BaseTestCase
class TestReleaseValidator(BaseTestCase):
def setUp(self):
super(TestReleaseValidator, self).setUp()
self.release = {
'name': 'Test Release',
'version': '2014.2-6.0',
'operating_system': 'CentOS',
'orchestrator_data': {
'puppet_manifests_source': 'path/to/manifests',
'puppet_modules_source': 'path/to/modules',
'repo_metadata': {
'repo': 'path/to/repo', }}}
self.validator = ReleaseValidator
def get_release(self, release):
return jsonutils.dumps(release)
def test_name_is_mandatory(self):
self.release.pop('name')
self.assertRaisesRegexp(
errors.InvalidData,
'No release name specified',
self.validator.validate,
self.get_release(self.release))
def test_version_is_mandatory(self):
self.release.pop('version')
self.assertRaisesRegexp(
errors.InvalidData,
'No release version specified',
self.validator.validate,
self.get_release(self.release))
def test_operating_system_is_mandatory(self):
self.release.pop('operating_system')
self.assertRaisesRegexp(
errors.InvalidData,
'No release operating system specified',
self.validator.validate,
self.get_release(self.release))
def test_orchestrator_data_is_mandatory(self):
self.release.pop('orchestrator_data')
self.assertRaisesRegexp(
errors.InvalidData,
'No orchestrator_data specified',
self.validator.validate,
self.get_release(self.release))
def test_orchestrator_data_must_be_a_dict(self):
self.release['orchestrator_data'] = None
self.assertRaisesRegexp(
errors.InvalidData,
"'orchestrator_data' field must be a dict",
self.validator.validate,
self.get_release(self.release))
def test_orchestrator_data_required_keys(self):
self.release['orchestrator_data'] = {}
self.assertRaisesRegexp(
errors.InvalidData,
"'orchestrator_data' doesn't have all required keys",
self.validator.validate,
self.get_release(self.release))
def test_default_are_good(self):
self.validator.validate(self.get_release(self.release))