O4S for Software

O4S for IT Security

O4S for Services

RedHatHow to download a package from a custom channel? RHN Satellite take care of generating repodata directory structure as primary.xml, but package location are reference to getPackage/full_package.rpm and the RHN Satellite 5.6 downloadFile.do does not handle correctly them if not handled by cobbler.

 

So, to solve it, I wrote a small program based on RHN Satellite API: rhn_downloadFile.php

 

 

 

<?php

/*

Copyright 2015, Pascal TROUVIN, O4S.FR

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.

*/

class RpcClient {
    
    private $_methods;
    private $_context;
    private $_url;
    private $key;
    
    private $debug=0;
    
    function __construct ($url, $user, $passwd) {
        if( isset($user) && $user!=NULL ){
            $auth = base64_encode(sprintf('%s:%s', $user,$passwd));
            $this->_context = stream_context_create(array(
                'http' => array(
                    'method' => 'POST',
                    'header' => "Content-Type: text/xml\r\n".
                                "Authorization: Basic $auth" ,
                    
                )
            ));
        } else {
            $this->_context = stream_context_create(array(
                'http' => array(
                    'method' => 'POST',
                    'header' => "Content-Type: text/xml\r\n",
                    
                )
            ));
        }
        $this->_url = $url;
        
        $this->registerMethod ("auth.login");
        $this->registerMethod ("auth.logout");
        $this->registerMethod ("packages.search.name");
        $this->registerMethod ("packages.search.advanced");
        $this->registerMethod ("packages.getPackage");
        $this->registerMethod ("packages.getPackageUrl");
    }

    function debug($debug){
        $this->debug=$debug;
    }
    
    function login($user, $passwd){
        $this->key=$this->__call("auth.login",array($user,$passwd));
        return $this->key;
    }
    function logout(){
        return $this->__call("auth.logout",array($this->key));
    }
    function getPackage($name){
        header("X-Debug-getPackage: name($name)");
        $ls=$this->__call("packages.search.name",array($this->key,$name));
        $this->getPackageCore($name,$ls);
    }

    function getPackageAdvanced($name, $version, $release, $arch){
        header("X-Debug-getPackageAdvanced: name($name) version($version) release($release) arch($arch)");
        $luceneQuery="name:$name AND version:$version AND release:$release AND arch:$arch";
        header("X-Debug-luceneQuery: $luceneQuery");
        $ls=$this->__call("packages.search.advanced",array($this->key,$luceneQuery));
        $this->getPackageCore($name,$ls);
    }
    
    function getPackageCore($name,$ls){
        if( $this->debug>0 )
            print_r($ls);
        else {
            # filter strict equality to name
            $pkgs=array();
            if(count($ls)==1)
                $pkgs=$ls;
            else
                foreach($ls as $p){
                    if( strpos($p['name'],$name)!==false )
                        array_push($pkgs, $p);
                    else
                        header("X-Package-refused: ".$p['name'],false);
                }
            if( count($pkgs)>1 ){
                # more than one rpm, so list them
                header("Content-Type: text/html",true);
                echo "<p>List of package named: $name</p>\n<ul>\n";
                foreach($pkgs as $p){
                    echo "<li>(".$p['id'].")".$p['name']."</li>\n";
                }
                echo "</ul>\n";
            } else {
                foreach($pkgs as $p){
                    header("X-GetPackage: (".$p['id'].")".$p['name'],false);
                    #$this->getPackageId($p['name'], $p['id'], $p['version'], $p['release'], $p['arch']);
                    $this->getPackageUrl($p['id']);
                }
            }
        }
    }

    function getPackageUrl($id){
        $pkgurl=$this->__call("packages.getPackageUrl",array($this->key,intval($id)));
        header("Location: $pkgurl",true);
        exit;
    }
    
    
    
    
    function __call($methodName, $params) {
        if (array_key_exists($methodName,$this->_methods)) {
            // on appelle la fonction RPC
            #$m = str_replace('_', '.', $methodName);
            $m=$methodName;
            $r = xmlrpc_encode_request($m, $params,array('verbosity'=>'newlines_only'));
            $c = $this->_context;
            stream_context_set_option($c,'http','content',$r);
            $f = file_get_contents($this->_url,false,$c);
            $resp = xmlrpc_decode($f);
            return $resp;
        } else {
            // on appelle la fonction de l'objet
            call_user_method_array($methodName, $this,$params);
        }
    }
    
    function registerMethod ($method) {
        $this->_methods[$method] = true;
    }
    
}

$id=isset($_GET['id']) ? $_GET['id'] : '';
$name=isset($_GET['name']) ? $_GET['name'] : '';
if( strlen($name)==0 && strlen($id)==0 ){
    echo "Missing parameter 'name' or 'id'\n";
    exit;
}
$debug=isset($_GET['debug']) ? $_GET['debug'] : 0;

if($debug>0){
    header("X-Debug-Name: $name");
    header("X-Debug-Id: $id");
}

$rpc=new RpcClient("http://RHN_SERVER/rpc/api",NULL,NULL);
$rpc->debug($debug);
if( $debug>1 )
    print_r($rpc);
$r=$rpc->login("RHN_USERNAME","RHN_PASSWORD");
if( $debug>1 )
    print_r($r);
if( strlen($id)!=0 ){
    #$rpc->getPackageId((strlen($name)>0 ? $name:'download' ).".rpm",$id);
    $rpc->getPackageUrl($id);
} else {
    # $name is defined
    if( preg_match('/(.*)[.\-]([0-9]+[.\-][0-9]+)[.\-]([0-9]+)[.\-](x86_64|i386|i486|i586|i686|noarch)\.rpm$/', $name, $regs) ){
        $rpc->getPackageAdvanced($regs[1], $regs[2], $regs[3], $regs[4]);
    } else {
        $rpc->getPackage($name);
    }
}
$rpc->logout();
?>