diff --git a/anvil/packaging/helpers/py2rpm_helper.py b/anvil/packaging/helpers/py2rpm_helper.py index 25e24f43..b1b93907 100644 --- a/anvil/packaging/helpers/py2rpm_helper.py +++ b/anvil/packaging/helpers/py2rpm_helper.py @@ -93,9 +93,10 @@ class Helper(object): def _convert_names_to_rpm(self, python_names, only_name): if not python_names: - return {} + return {}, {} cmdline = self._start_cmdline() + ["--convert"] + python_names result = collections.defaultdict(set) + conflicts = collections.defaultdict(set) current_source = None for line in sh.execute(cmdline)[0].splitlines(): # NOTE(harlowja): format is "Requires: rpm-name <=> X" or when @@ -109,6 +110,9 @@ class Helper(object): if positions: line = line[0:positions[0]] result[current_source].add(line.strip()) + elif line.startswith("Conflicts:"): + line = line[len("Conflicts:"):] + conflicts[current_source].add(line.strip()) elif line.startswith("# Source:"): current_source = line[len("# Source:"):].strip() @@ -120,10 +124,10 @@ class Helper(object): if extra_names: raise AssertionError("Extra python names were found during conversion: %s" % ', '.join(sorted(extra_names))) - return result + return result, conflicts def names_to_rpm_names(self, python_names): - mapping = self._convert_names_to_rpm(python_names, only_name=True) + mapping = self._convert_names_to_rpm(python_names, only_name=True)[0] result = {} for k, v in six.iteritems(mapping): assert len(v) == 1, ('There should be exactly one RPM name for ' @@ -132,11 +136,13 @@ class Helper(object): result[k] = v.pop() return result - def names_to_rpm_requires(self, python_names): - mapping = self._convert_names_to_rpm(python_names, only_name=False) - return [req - for value in six.itervalues(mapping) - for req in value] + def names_to_rpm_deps(self, python_names): + # Given a set of packages in Python namespace, return the equivalent + # Requires and Conflicts in RPM namespace. + requires, conflicts = self._convert_names_to_rpm(python_names, only_name=False) + requires_list = [req for value in six.itervalues(requires) for req in value] + conflicts_list = [req for value in six.itervalues(conflicts) for req in value] + return requires_list, conflicts_list def build_all_srpms(self, package_files, tracewriter, jobs): (_fn, content) = utils.load_template(sh.joinpths("packaging", "makefiles"), "source.mk") diff --git a/anvil/packaging/yum.py b/anvil/packaging/yum.py index 3297f5f5..aa665c91 100644 --- a/anvil/packaging/yum.py +++ b/anvil/packaging/yum.py @@ -632,7 +632,9 @@ class YumDependencyHandler(base.DependencyHandler): def _write_spec_file(self, instance, rpm_name, template_name, params): requires_what = params.get('requires', []) + conflicts_what = params.get('conflicts', []) test_requires_what = params.get('test_requires', []) + test_conflicts_what = params.get('test_conflicts', []) egg_info = getattr(instance, 'egg_info', None) if egg_info: @@ -640,15 +642,21 @@ class YumDependencyHandler(base.DependencyHandler): try: requires_python = [str(req) for req in egg_info[key]] except KeyError: - return [] + return [], [] else: - return self.py2rpm_helper.names_to_rpm_requires(requires_python) + return self.py2rpm_helper.names_to_rpm_deps(requires_python) - requires_what.extend(ei_names('dependencies')) - test_requires_what.extend(ei_names('test_dependencies')) + rpm_requires, rpm_conflicts = ei_names('dependencies') + requires_what.extend(rpm_requires) + conflicts_what.extend(rpm_conflicts) + rpm_test_requires, rpm_test_conflicts = ei_names('test_dependencies') + test_requires_what.extend(rpm_test_requires) + test_conflicts_what.extend(rpm_test_conflicts) params["requires"] = requires_what + params["conflicts"] = conflicts_what params["test_requires"] = test_requires_what + params["test_conflicts"] = test_conflicts_what params["epoch"] = self.OPENSTACK_EPOCH params["part_fn"] = lambda filename: sh.joinpths( settings.TEMPLATE_DIR, diff --git a/conf/templates/packaging/specs/openstack-ceilometer.spec b/conf/templates/packaging/specs/openstack-ceilometer.spec index 69dc84af..87c2a729 100644 --- a/conf/templates/packaging/specs/openstack-ceilometer.spec +++ b/conf/templates/packaging/specs/openstack-ceilometer.spec @@ -96,6 +96,10 @@ Group: Applications/System Requires: ${i} #end for +#for $i in $conflicts +Conflicts: ${i} +#end for + %description -n python-ceilometer OpenStack ceilometer provides services to measure and collect metrics from OpenStack components. diff --git a/conf/templates/packaging/specs/openstack-cinder.spec b/conf/templates/packaging/specs/openstack-cinder.spec index d52c985f..ef0abc1d 100644 --- a/conf/templates/packaging/specs/openstack-cinder.spec +++ b/conf/templates/packaging/specs/openstack-cinder.spec @@ -77,6 +77,10 @@ Requires: sudo Requires: ${i} #end for +#for $i in $conflicts +Conflicts: ${i} +#end for + %description -n python-cinder OpenStack Volume (codename Cinder) provides services to manage and diff --git a/conf/templates/packaging/specs/openstack-glance.spec b/conf/templates/packaging/specs/openstack-glance.spec index d992088c..c289e048 100644 --- a/conf/templates/packaging/specs/openstack-glance.spec +++ b/conf/templates/packaging/specs/openstack-glance.spec @@ -75,6 +75,10 @@ Group: Applications/System Requires: ${i} #end for +#for $i in $conflicts +Conflicts: ${i} +#end for + %description -n python-glance OpenStack Image Service (code-named Glance) provides discovery, registration, and delivery services for virtual disk images. diff --git a/conf/templates/packaging/specs/openstack-heat.spec b/conf/templates/packaging/specs/openstack-heat.spec index cf3cc88c..cb29d143 100644 --- a/conf/templates/packaging/specs/openstack-heat.spec +++ b/conf/templates/packaging/specs/openstack-heat.spec @@ -128,6 +128,10 @@ Requires: ${i} Requires(pre): shadow-utils %endif +#for $i in $conflicts +Conflicts: ${i} +#end for + %description common Components common to all OpenStack Heat services diff --git a/conf/templates/packaging/specs/openstack-ironic.spec b/conf/templates/packaging/specs/openstack-ironic.spec index 3f41bd3b..3bc22c67 100644 --- a/conf/templates/packaging/specs/openstack-ironic.spec +++ b/conf/templates/packaging/specs/openstack-ironic.spec @@ -95,6 +95,10 @@ Group: Applications/System Requires: ${i} #end for +#for $i in $conflicts +Conflicts: ${i} +#end for + %description -n python-%{python_name} This package contains the %{name} Python library. diff --git a/conf/templates/packaging/specs/openstack-keystone.spec b/conf/templates/packaging/specs/openstack-keystone.spec index 39e31167..7057b784 100644 --- a/conf/templates/packaging/specs/openstack-keystone.spec +++ b/conf/templates/packaging/specs/openstack-keystone.spec @@ -105,6 +105,10 @@ Group: Development/Languages/Python Requires: ${i} #end for +#for $i in $conflicts +Conflicts: ${i} +#end for + %description -n python-keystone Keystone is a Python implementation of the OpenStack (http://www.openstack.org) identity service API. diff --git a/conf/templates/packaging/specs/openstack-neutron.spec b/conf/templates/packaging/specs/openstack-neutron.spec index c40583b9..ff39a3c8 100644 --- a/conf/templates/packaging/specs/openstack-neutron.spec +++ b/conf/templates/packaging/specs/openstack-neutron.spec @@ -134,6 +134,9 @@ Requires: sudo Requires: ${i} #end for +#for $i in $conflicts +Conflicts: ${i} +#end for %description -n python-neutron Neutron provides an API to dynamically request and configure virtual diff --git a/conf/templates/packaging/specs/openstack-nova.spec b/conf/templates/packaging/specs/openstack-nova.spec index b796c615..5018556d 100644 --- a/conf/templates/packaging/specs/openstack-nova.spec +++ b/conf/templates/packaging/specs/openstack-nova.spec @@ -348,6 +348,10 @@ Requires: sudo Requires: ${i} #end for +#for $i in $conflicts +Conflicts: ${i} +#end for + %description -n python-nova OpenStack Compute (codename Nova) is open source software designed to provision and manage large networks of virtual machines, creating a diff --git a/conf/templates/packaging/specs/openstack-trove.spec b/conf/templates/packaging/specs/openstack-trove.spec index 880618a1..dc9d0528 100644 --- a/conf/templates/packaging/specs/openstack-trove.spec +++ b/conf/templates/packaging/specs/openstack-trove.spec @@ -87,6 +87,10 @@ Group: Development/Languages/Python Requires: ${i} #end for +#for $i in $conflicts +Conflicts: ${i} +#end for + %description -n python-trove Trove is Database as a Service for Openstack. It's designed to run entirely on OpenStack, with the goal of allowing users to quickly and diff --git a/conf/templates/packaging/specs/python-commonclient.spec b/conf/templates/packaging/specs/python-commonclient.spec index 190ae10b..66248aa2 100644 --- a/conf/templates/packaging/specs/python-commonclient.spec +++ b/conf/templates/packaging/specs/python-commonclient.spec @@ -55,6 +55,10 @@ BuildRequires: make Requires: ${i} #end for +#for $i in $conflicts +Conflicts: ${i} +#end for + %description This is a client for the OpenStack $apiname API. There's a Python API (the ${clientname}client module), and a command-line script (${clientname}). diff --git a/conf/templates/packaging/specs/python-django-horizon.spec b/conf/templates/packaging/specs/python-django-horizon.spec index a6b56778..a8606db5 100644 --- a/conf/templates/packaging/specs/python-django-horizon.spec +++ b/conf/templates/packaging/specs/python-django-horizon.spec @@ -72,6 +72,10 @@ BuildRequires: python-scss Requires: ${i} #end for +#for $i in $conflicts +Conflicts: ${i} +#end for + %description Horizon is a Django application for providing Openstack UI components. It allows performing site administrator (viewing account resource usage,