[Spacewalk-list] Ubuntu 18.04 package management in Spacewalk 2.8

Paul-Andre Panon paul-andre.panon at avigilon.com
Thu Dec 20 21:23:34 UTC 2018


On Tuesday, December 18, 2018 2:59 PM, I wrote that I thought I had a
solution to the phantom packages with Ubuntu that I hadn't tested yet.

OK, there were a few typos and syntax errors, but this corrected stored
proc appears to work well.

    SET search_path = rpm, pg_catalog;
    create or replace FUNCTION rpmstrcmp (string1 IN VARCHAR, string2 IN
VARCHAR)
    RETURNS INTEGER as $$
    declare
        str1 VARCHAR := string1;
        str2 VARCHAR := string2;
        digits VARCHAR(10) := '0123456789';
        lc_alpha VARCHAR(27) := 'abcdefghijklmnopqrstuvwxyz';
        uc_alpha VARCHAR(27) := 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        alpha VARCHAR(54) := lc_alpha || uc_alpha;
        one VARCHAR;
        two VARCHAR;
        sep1 VARCHAR;
        sep2 VARCHAR;
        isnum BOOLEAN;
    BEGIN
        if str1 is NULL or str2 is NULL
        then
            RAISE EXCEPTION 'VALUE_ERROR.';
        end if;

        if str1 = str2
        then
            return 0;
        end if;
        one := str1;
        two := str2;

        <<segment_loop>>
        while one <> '' and two <> ''
        loop
            declare
                segm1 VARCHAR;
                segm2 VARCHAR;
            begin
                sep1 := '';
                sep2 := '';
                --DBMS_OUTPUT.PUT_LINE('Params: ' || one || ',' || two);
                -- Pull out all separating non-alphanum characters
                while one <> '' and not rpm.isalphanum(one)
                loop
                    sep1 := sep1 || substr(one, 1, 1);
                    one := substr(one, 2);
                end loop;
                while two <> '' and not rpm.isalphanum(two)
                loop
                    sep2 := sep2 || substr(two, 1, 1);
                    two := substr(two, 2);
                end loop;

                str1 := one;
                str2 := two;
                if str1 <> '' and rpm.isdigit(str1)
                then
                    str1 := ltrim(str1, digits);
                    str2 := ltrim(str2, digits);
                    isnum := true;
                else
                    str1 := ltrim(str1, alpha);
                    str2 := ltrim(str2, alpha);
                    isnum := false;
                end if;
                if str1 <> ''
                then segm1 := substr(one, 1, length(one) - length(str1));
                else segm1 := one;
                end if;

                if str2 <> ''
                then segm2 := substr(two, 1, length(two) - length(str2));
                else segm2 := two;
                end if;

                -- if one of the separators is for a point subversion
indicator and the other isn't, then the point subversion is considered
more recent.
                if isnum and sep1 <> '' and sep2 <> ''
                then
                    if sep1 = '.' and sep2 <> '.'
                    then
                        return 1;
					elsif sep2 = '.' and sep1 <> '.'
                    then
                        return -1;
					end if;
                end if;

                if segm1 = '' then return -1; end if; /* arbitrary */
                if segm2 = '' then
                    if isnum then
                        return 1;
                    else
                        return -1;
                    end if;
                end if;
                if isnum
                then
                    segm1 := ltrim(segm1, '0');
                    segm2 := ltrim(segm2, '0');

                    if segm1 = '' and segm2 <> ''
                    then
                        return -1;
                    end if;
                    if segm1 <> '' and segm2 = ''
                    then
                        return 1;
                    end if;
                    if length(segm1) > length(segm2) then return 1; end
if;
                    if length(segm2) > length(segm1) then return -1; end
if;
                end if;
                if segm1 < segm2 then return -1; end if;
                if segm1 > segm2 then return 1; end if;
                one := str1;
                two := str2;
            end;
        end loop segment_loop;

        if one = '' and two = '' then return 0; end if;
        if one = '' then return -1; end if;
        return 1;
    END ;
$$ language 'plpgsql';

ALTER FUNCTION rpm.rpmstrcmp(string1 character varying, string2 character
varying) OWNER TO spaceuser;


I incorporated that into a duplicate of our postgres database. Then I ran
the following query on both the unpatched and modified DBs
select sp.server_id, count(*)
           FROM (SELECT sp_sp.server_id, sp_sp.name_id,
        sp_sp.package_arch_id, max(sp_pe.evr) AS max_evr
                   FROM rhnServerPackage sp_sp
                   join rhnPackageEvr sp_pe ON sp_pe.id = sp_sp.evr_id
                  GROUP BY sp_sp.server_id, sp_sp.name_id,
sp_sp.package_arch_id) sp
           join rhnPackage p ON p.name_id = sp.name_id
           join rhnPackageEvr pe ON pe.id = p.evr_id AND sp.max_evr <
pe.evr
           join rhnPackageUpgradeArchCompat puac
            ON puac.package_arch_id = sp.package_arch_id
        AND puac.package_upgrade_arch_id = p.package_arch_id
           join rhnServerChannel sc ON sc.server_id = sp.server_id
           join rhnChannelPackage cp ON cp.package_id = p.id
            AND cp.channel_id = sc.channel_id
group by sp.server_id
order by sp.server_id;

Wherever there were differences in package counts, I looked at the
individual package evrs with
select sp.server_id, p.id, sp.max_evr, pe.evr
           FROM (SELECT sp_sp.server_id, sp_sp.name_id,
        sp_sp.package_arch_id, max(sp_pe.evr) AS max_evr
                   FROM rhnServerPackage sp_sp
                   join rhnPackageEvr sp_pe ON sp_pe.id = sp_sp.evr_id
                  GROUP BY sp_sp.server_id, sp_sp.name_id,
sp_sp.package_arch_id) sp
           join rhnPackage p ON p.name_id = sp.name_id
           join rhnPackageEvr pe ON pe.id = p.evr_id AND sp.max_evr <
pe.evr
           join rhnPackageUpgradeArchCompat puac
            ON puac.package_arch_id = sp.package_arch_id
        AND puac.package_upgrade_arch_id = p.package_arch_id
           join rhnServerChannel sc ON sc.server_id = sp.server_id
           join rhnChannelPackage cp ON cp.package_id = p.id
            AND cp.channel_id = sc.channel_id
where sp.server_id IN (<server id list with discrepancies>) order by
sp.server_id, p.id;

The updated SP corrected the erroneous false positives, and also caught
some packages which needed to be updated but weren't listed. Can somebody
put this in a PR?

Thanks,

Paul-Andre




More information about the Spacewalk-list mailing list