Merge "Add svc-map element."
This commit is contained in:
commit
78be2a21fe
103
elements/svc-map/README.md
Normal file
103
elements/svc-map/README.md
Normal file
@ -0,0 +1,103 @@
|
||||
Map service names to distro specific services.
|
||||
|
||||
Provides the following:
|
||||
|
||||
* bin/svc-map
|
||||
|
||||
usage: svc-map [-h] SERVICE
|
||||
|
||||
Translate service name to distro specific name.
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
|
||||
* Any element may create its own svc-map YAML config file using
|
||||
the one of 3 sections for the distro/family/ and or default.
|
||||
The family is set automatically within svc-map based on
|
||||
the supplied distro name. Families include:
|
||||
+ redhat: includes centos, fedora, and rhel distros
|
||||
+ debian: includes debian and ubuntu distros
|
||||
+ suse: includes the opensuse distro
|
||||
|
||||
The most specific section takes priority. Example for Nova and Glance
|
||||
(NOTE: default is using the common value for redhat and suse families)
|
||||
|
||||
The key used for the service name should always be the same name used for
|
||||
the source installation of the service. The svc-map script will check for
|
||||
the source name against systemd and upstart and return that name if it
|
||||
exists instead of the mapped name.
|
||||
|
||||
Example format for Nova:
|
||||
|
||||
nova-api:
|
||||
default: openstack-nova-api
|
||||
debian: nova-api
|
||||
nova-cert:
|
||||
default: openstack-nova-cert
|
||||
debian: nova-cert
|
||||
nova-compute:
|
||||
default: openstack-nova-compute
|
||||
debian: nova-compute
|
||||
nova-conductor:
|
||||
default: openstack-nova-conductor
|
||||
debian: nova-conductor
|
||||
nova-consoleauth:
|
||||
default: openstack-nova-console
|
||||
debian: nova-console
|
||||
|
||||
|
||||
Example format for Glance
|
||||
|
||||
glance-api:
|
||||
debian: glance-api
|
||||
default: openstack-glance-api
|
||||
glance-reg:
|
||||
debian: glance-reg
|
||||
default: openstack-glance-registry
|
||||
|
||||
|
||||
If the distro is of the debian family the combined services file would be:
|
||||
|
||||
nova-cert: nova-cert
|
||||
nova-compute: nova-compute
|
||||
glance-api: glance-api
|
||||
nova-conductor: nova-conductor
|
||||
nova-api: nova-api
|
||||
glance-reg: glance-reg
|
||||
nova-consoleauth: nova-console
|
||||
|
||||
|
||||
If the distro is of the suse or redhat families the combined services file would be:
|
||||
|
||||
nova-cert: openstack-nova-cert
|
||||
nova-compute: openstack-nova-compute
|
||||
glance-reg: openstack-glance-registry
|
||||
nova-conductor: openstack-nova-conductor
|
||||
glance-api: openstack-glance-api
|
||||
nova-consoleauth: openstack-nova-console
|
||||
nova-api: openstack-nova-api
|
||||
|
||||
|
||||
Example commands using this format:
|
||||
|
||||
svc-map nova-compute
|
||||
|
||||
Returns: openstack-nova-compute
|
||||
|
||||
svc-map nova-compute
|
||||
|
||||
Returns: openstack-nova-compute
|
||||
|
||||
svc-map nova-compute
|
||||
|
||||
Returns: nova-compute
|
||||
|
||||
* This output can be used to filter what other tools actually install
|
||||
(install-services can be modified to use this for example)
|
||||
|
||||
* If you pass more than one service argument, the result for each service
|
||||
is printed on its own line.
|
||||
|
||||
* Individual svc-map files live within each element. For example
|
||||
if you have created an Apache element your svc-map YAML file
|
||||
should be created at elements/apache/svc-map.
|
46
elements/svc-map/bin/svc-map
Executable file
46
elements/svc-map/bin/svc-map
Executable file
@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright 2012 Hewlett-Packard Development Company, L.P.
|
||||
# Copyright 2014 Red Hat, 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.
|
||||
import os
|
||||
import sys
|
||||
import yaml
|
||||
|
||||
|
||||
def load_service_mapping(filepath="/usr/share/svc-map/services"):
|
||||
if not os.path.isfile(filepath):
|
||||
return {}
|
||||
with open(filepath, 'r') as data_file:
|
||||
return yaml.load(data_file.read())
|
||||
|
||||
|
||||
def main():
|
||||
for arg in sys.argv[1:]:
|
||||
# We need to support the service name being different when installing
|
||||
# from source vs. packages. So, if the requested service file already
|
||||
# exists, just use that.
|
||||
if os.path.exists('/lib/systemd/system/%s.service' % arg): # systemd
|
||||
print(arg)
|
||||
elif os.path.exists('/etc/init/%s.conf' % arg): # upstart
|
||||
print(arg)
|
||||
else:
|
||||
service_map = load_service_mapping()
|
||||
name = service_map.get(arg, arg)
|
||||
print(name)
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
70
elements/svc-map/extra-data.d/10-merge-svc-map-files
Executable file
70
elements/svc-map/extra-data.d/10-merge-svc-map-files
Executable file
@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env python
|
||||
import os
|
||||
import sys
|
||||
import yaml
|
||||
|
||||
|
||||
def os_family(distro):
|
||||
"""Given a distribution, returns a operating system family."""
|
||||
family = None
|
||||
if distro in ['centos', 'fedora', 'rhel', 'rhel7']:
|
||||
family = 'redhat'
|
||||
elif distro in ['debian', 'ubuntu']:
|
||||
family = 'debian'
|
||||
elif distro == 'opensuse':
|
||||
family = 'suse'
|
||||
return family
|
||||
|
||||
|
||||
def merge_data(source, destination, distro):
|
||||
"""Merges two dictionaries and filters on distro, family, or default
|
||||
(in order)."""
|
||||
result = dict()
|
||||
result.update(destination)
|
||||
family = os_family(distro)
|
||||
for servicename, mapping in source.iteritems():
|
||||
if servicename in result:
|
||||
raise Exception("%s already found in services list" % servicename)
|
||||
if distro in mapping:
|
||||
result[servicename] = mapping.get(distro)
|
||||
elif family in mapping:
|
||||
result[servicename] = mapping.get(family)
|
||||
elif 'default' in mapping:
|
||||
result[servicename] = mapping.get('default')
|
||||
else:
|
||||
result[servicename] = servicename
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def write_data_to_file(data, service_file_path):
|
||||
"""Writes yaml data to a specified path."""
|
||||
with open(service_file_path, 'w') as destination:
|
||||
yaml.dump(data, destination, default_flow_style=False)
|
||||
|
||||
|
||||
def main():
|
||||
elements = os.environ.get("IMAGE_ELEMENT").split(' ')
|
||||
element_paths = os.environ.get("ELEMENTS_PATH").split(':')
|
||||
service_names = dict()
|
||||
for element in elements:
|
||||
for element_path in element_paths:
|
||||
data_path = os.path.join(element_path, element, "svc-map")
|
||||
if os.path.exists(data_path):
|
||||
with open(data_path, 'r') as dataFile:
|
||||
data = yaml.load(dataFile.read())
|
||||
try:
|
||||
service_names = merge_data(
|
||||
data,
|
||||
service_names,
|
||||
os.environ.get("DISTRO_NAME"))
|
||||
except Exception as err:
|
||||
print("%s. Check %s for duplicate \
|
||||
service name." % (err, element))
|
||||
sys.exit(1)
|
||||
|
||||
write_data_to_file(service_names, os.path.join("/tmp", 'svc-map-services'))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
5
elements/svc-map/extra-data.d/11-copy-svc-map-file
Executable file
5
elements/svc-map/extra-data.d/11-copy-svc-map-file
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
set -eux
|
||||
set -o pipefail
|
||||
|
||||
sudo install -D -o root -g root -m 0644 /tmp/svc-map-services "$TMP_MOUNT_PATH/usr/share/svc-map/services"
|
179
elements/svc-map/tests/test_data_merge.py
Normal file
179
elements/svc-map/tests/test_data_merge.py
Normal file
@ -0,0 +1,179 @@
|
||||
# Copyright 2014 Red Hat, 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.
|
||||
import imp
|
||||
service_map = imp.load_source('service_map',
|
||||
'../extra-data.d/10-merge-svc-map-files')
|
||||
|
||||
from oslotest import base
|
||||
|
||||
|
||||
class TestDataMerge(base.BaseTestCase):
|
||||
|
||||
nova_api_services = {
|
||||
u'nova-api': {
|
||||
u'debian': u'nova-api',
|
||||
u'default': u'openstack-nova-api'
|
||||
},
|
||||
u'nova-cert': {
|
||||
u'debian': u'nova-cert',
|
||||
u'default': u'openstack-nova-cert'
|
||||
},
|
||||
u'nova-compute': {
|
||||
u'debian': u'nova-compute',
|
||||
u'default': u'openstack-nova-compute'
|
||||
},
|
||||
u'nova-conductor': {
|
||||
u'debian': u'nova-conductor',
|
||||
u'default': u'openstack-nova-conductor'
|
||||
},
|
||||
u'nova-consoleauth': {
|
||||
u'debian': u'nova-console',
|
||||
u'default': u'openstack-nova-console'
|
||||
}
|
||||
}
|
||||
|
||||
glance_api_services = {
|
||||
u'glance-api': {
|
||||
u'debian': u'glance-api',
|
||||
u'default': u'openstack-glance-api'
|
||||
},
|
||||
u'glance-reg': {
|
||||
u'debian': u'glance-reg',
|
||||
u'default': u'openstack-glance-registry'
|
||||
}
|
||||
}
|
||||
|
||||
cinder_api_services = {
|
||||
u'cinder-api': {
|
||||
u'debian': u'cinder-api',
|
||||
u'default': u'openstack-cinder-api'
|
||||
},
|
||||
u'cinder-scheduler': {
|
||||
u'debian': u'cinder-scheduler',
|
||||
u'default': u'openstack-cinder-scheduler'
|
||||
}
|
||||
}
|
||||
|
||||
def test_merge_data_fedora(self):
|
||||
|
||||
fedora_nova_api_services = {
|
||||
u'nova-api': u'openstack-nova-api',
|
||||
u'nova-cert': u'openstack-nova-cert',
|
||||
u'nova-compute': u'openstack-nova-compute',
|
||||
u'nova-conductor': u'openstack-nova-conductor',
|
||||
u'nova-consoleauth': u'openstack-nova-console'
|
||||
}
|
||||
|
||||
fedora_nova_glance_services = {
|
||||
u'nova-api': u'openstack-nova-api',
|
||||
u'nova-cert': u'openstack-nova-cert',
|
||||
u'nova-compute': u'openstack-nova-compute',
|
||||
u'nova-conductor': u'openstack-nova-conductor',
|
||||
u'nova-consoleauth': u'openstack-nova-console',
|
||||
u'glance-api': u'openstack-glance-api',
|
||||
u'glance-reg': u'openstack-glance-registry'
|
||||
}
|
||||
|
||||
fedora_nova_glance_cinder_services = {
|
||||
u'nova-api': u'openstack-nova-api',
|
||||
u'nova-cert': u'openstack-nova-cert',
|
||||
u'nova-compute': u'openstack-nova-compute',
|
||||
u'nova-conductor': u'openstack-nova-conductor',
|
||||
u'nova-consoleauth': u'openstack-nova-console',
|
||||
u'glance-api': u'openstack-glance-api',
|
||||
u'glance-reg': u'openstack-glance-registry',
|
||||
u'cinder-api': u'openstack-cinder-api',
|
||||
u'cinder-scheduler': u'openstack-cinder-scheduler',
|
||||
}
|
||||
|
||||
result = dict()
|
||||
result = service_map.merge_json(self.nova_api_services,
|
||||
result,
|
||||
"fedora")
|
||||
|
||||
self.assertDictEqual(result,
|
||||
fedora_nova_api_services,
|
||||
"Merge failed")
|
||||
|
||||
result = service_map.merge_json(self.glance_api_services,
|
||||
result,
|
||||
"fedora")
|
||||
|
||||
self.assertDictEqual(result,
|
||||
fedora_nova_glance_services,
|
||||
"Merge failed")
|
||||
|
||||
result = service_map.merge_json(self.cinder_api_services,
|
||||
result,
|
||||
"fedora")
|
||||
self.assertDictEqual(result,
|
||||
fedora_nova_glance_cinder_services,
|
||||
"Merge failed")
|
||||
|
||||
def test_merge_data_ubuntu(self):
|
||||
|
||||
ubuntu_nova_api_services = {
|
||||
u'nova-api': u'nova-api',
|
||||
u'nova-cert': u'nova-cert',
|
||||
u'nova-compute': u'nova-compute',
|
||||
u'nova-conductor': u'nova-conductor',
|
||||
u'nova-consoleauth': u'nova-console'
|
||||
}
|
||||
|
||||
ubuntu_nova_glance_services = {
|
||||
u'nova-api': u'nova-api',
|
||||
u'nova-cert': u'nova-cert',
|
||||
u'nova-compute': u'nova-compute',
|
||||
u'nova-conductor': u'nova-conductor',
|
||||
u'nova-consoleauth': u'nova-console',
|
||||
u'glance-api': u'glance-api',
|
||||
u'glance-reg': u'glance-reg'
|
||||
}
|
||||
|
||||
ubuntu_nova_glance_cinder_services = {
|
||||
u'nova-api': u'nova-api',
|
||||
u'nova-cert': u'nova-cert',
|
||||
u'nova-compute': u'nova-compute',
|
||||
u'nova-conductor': u'nova-conductor',
|
||||
u'nova-consoleauth': u'nova-console',
|
||||
u'glance-api': u'glance-api',
|
||||
u'glance-reg': u'glance-reg',
|
||||
u'cinder-api': u'cinder-api',
|
||||
u'cinder-scheduler': u'cinder-scheduler'
|
||||
}
|
||||
|
||||
result = dict()
|
||||
result = service_map.merge_json(self.nova_api_services,
|
||||
result,
|
||||
"ubuntu")
|
||||
|
||||
self.assertDictEqual(result,
|
||||
ubuntu_nova_api_services,
|
||||
"Merge failed")
|
||||
|
||||
result = service_map.merge_json(self.glance_api_services,
|
||||
result,
|
||||
"ubuntu")
|
||||
|
||||
self.assertDictEqual(result,
|
||||
ubuntu_nova_glance_services,
|
||||
"Merge failed")
|
||||
|
||||
result = service_map.merge_json(self.cinder_api_services,
|
||||
result,
|
||||
"ubuntu")
|
||||
|
||||
self.assertDictEqual(result,
|
||||
ubuntu_nova_glance_cinder_services,
|
||||
"Merge failed")
|
@ -5,5 +5,6 @@ hacking>=0.9.2,<0.10
|
||||
|
||||
coverage>=3.6
|
||||
discover
|
||||
oslotest>=1.1.0
|
||||
testrepository>=0.0.18
|
||||
testtools>=0.9.34
|
||||
|
Loading…
Reference in New Issue
Block a user