This version incorporates a temporary fix for this pulp-admin issue
https://bugzilla.redhat.com/show_bug.cgi?id=629718 by overwriting
server.py in the pulp package.
Pulp must be installed before you apply this patch. Instructions here:
http://pulpproject.org/ug/UGInstallation.html#installation
The steps in the puppet pulp script are:
1. check pulp rpm is installed
2. write out templatized configuration files
3. replace pulp's server.py to fix issue with pulp-admin
4. start pulp-server service
5. initialize pulp
6. save default credentials (may need to change admin password)
7. create x86_64 repos for f13 and f14
8. trigger a sync on both repos
Syncs run in the background. The first sync may take some time to complete
depending on your network bandwidth. Use "pulp-admin repo status --id" to
check the status of the sync using f13-x86_64 and f14-x86_64 for the
repo id.
---
recipes/aeolus_recipe/aeolus_recipe.pp | 2 +-
recipes/aeolus_recipe/aeolus_uninstall.pp | 2 +-
recipes/aeolus_recipe/manifests/aeolus.pp | 2 +-
recipes/aeolus_recipe/manifests/pulp.pp | 79 +++++
recipes/aeolus_recipe/templates/pulp-client.conf | 49 ++++
.../templates/pulp-temp-fix-server.py | 302 ++++++++++++++++++++
recipes/aeolus_recipe/templates/pulp.conf | 119 ++++++++
7 files changed, 552 insertions(+), 3 deletions(-)
create mode 100644 recipes/aeolus_recipe/manifests/pulp.pp
create mode 100755 recipes/aeolus_recipe/templates/pulp-client.conf
create mode 100644 recipes/aeolus_recipe/templates/pulp-temp-fix-server.py
create mode 100644 recipes/aeolus_recipe/templates/pulp.conf
diff --git a/recipes/aeolus_recipe/aeolus_recipe.pp
b/recipes/aeolus_recipe/aeolus_recipe.pp
index dd05dc3..82b3e54 100644
--- a/recipes/aeolus_recipe/aeolus_recipe.pp
+++ b/recipes/aeolus_recipe/aeolus_recipe.pp
@@ -30,6 +30,7 @@ import "aeolus_recipe/defaults"
include aeolus::conductor
include aeolus::image-factory
include aeolus::iwhd
+include aeolus::pulp
aeolus::create_bucket{"aeolus":}
@@ -68,4 +69,3 @@ aeolus::conductor::hwp{"hwp1":
login_user => 'admin',
login_password => 'password',
require => Aeolus::Site_admin["admin"] }
-
diff --git a/recipes/aeolus_recipe/aeolus_uninstall.pp
b/recipes/aeolus_recipe/aeolus_uninstall.pp
index c0b0eae..8dba827 100644
--- a/recipes/aeolus_recipe/aeolus_uninstall.pp
+++ b/recipes/aeolus_recipe/aeolus_uninstall.pp
@@ -30,8 +30,8 @@ import "aeolus_recipe/defaults"
include aeolus::conductor::disabled
include aeolus::iwhd::disabled
include aeolus::image-factory::disabled
+include aeolus::pulp::disabled
aeolus::deltacloud::disabled{"mock": }
aeolus::deltacloud::disabled{"ec2-us-east-1": }
aeolus::deltacloud::disabled{"ec2-us-west-1": }
-
diff --git a/recipes/aeolus_recipe/manifests/aeolus.pp
b/recipes/aeolus_recipe/manifests/aeolus.pp
index de43f9c..d94ed38 100644
--- a/recipes/aeolus_recipe/manifests/aeolus.pp
+++ b/recipes/aeolus_recipe/manifests/aeolus.pp
@@ -10,6 +10,7 @@ import "conductor"
import "deltacloud"
import "iwhd"
import "image-factory"
+import "pulp"
if $aeolus_enable_https == "true" or $aeolus_enable_https == "1" {
import "openssl"
@@ -63,4 +64,3 @@ define aeolus::provider($type, $port, $login_user="",
$login_password=""){
login_password => $login_password,
require => Aeolus::Deltacloud[$name] }
}
-
diff --git a/recipes/aeolus_recipe/manifests/pulp.pp
b/recipes/aeolus_recipe/manifests/pulp.pp
new file mode 100644
index 0000000..4baf1d8
--- /dev/null
+++ b/recipes/aeolus_recipe/manifests/pulp.pp
@@ -0,0 +1,79 @@
+# Aeolus pulp puppet definitions
+
+class aeolus::pulp inherits aeolus {
+ package { 'pulp':
+ ensure => 'installed'
+ }
+
+ file { 'pulp-conf-file-pulp':
+ path => '/etc/pulp/pulp.conf',
+ owner => root,
+ group => root,
+ content => template("aeolus_recipe/pulp.conf")
+ }
+
+ file { 'pulp-conf-file-client':
+ path => '/etc/pulp/client.conf',
+ owner => apache,
+ group => apache,
+ content => template("aeolus_recipe/pulp-client.conf")
+ }
+
+ # FIXME: remove when fix is available in next pulp release
+ file { 'pulp-temp-fix-server':
+ path => '/usr/lib/python2.7/site-packages/pulp/client/server.py',
+ owner => root,
+ group => root,
+ replace => true,
+ content => template("aeolus_recipe/pulp-temp-fix-server.py")
+ }
+
+ exec{'pulp-init':
+ command => "/sbin/service pulp-server init",
+ logoutput => true,
+ require => [Package['pulp'],
+ File['pulp-conf-file-pulp'],
+ File['pulp-conf-file-client'],
+ File['pulp-temp-fix-server']]}
+
+ service { 'pulp-server':
+ ensure => 'running',
+ enable => true,
+ require => [Package['pulp'],
+ Exec["pulp-init"]]}
+
+ exec{'pulp-auth':
+ command => "/usr/bin/pulp-admin -u admin -p admin auth login --username admin
--password admin",
+ logoutput => true,
+ require => Service['pulp-server']}
+
+ exec{'pulp-f13-x86-64-repo-create':
+ command => "/usr/bin/pulp-admin repo create --id f13-x86_64 --feed
yum:http://download.fedoraproject.org/pub/fedora/linux/releases/13/Fedora...;,
+ logoutput => true,
+ creates =>
"/var/lib/pulp/repos/pub/fedora/linux/releases/13/Fedora/x86_64/os",
+ require => Exec['pulp-auth']}
+
+ exec{'pulp-f13-x86-64-repo-sync':
+ command => "/usr/bin/pulp-admin repo sync --id f13-x86_64",
+ logoutput => true,
+ require => Exec['pulp-f13-x86-64-repo-create']}
+
+ exec{'pulp-f14-x86-64-repo-create':
+ command => "/usr/bin/pulp-admin repo create --id f14-x86_64 --feed
yum:http://download.fedoraproject.org/pub/fedora/linux/releases/14/Fedora...;,
+ logoutput => true,
+ creates =>
"/var/lib/pulp/repos/pub/fedora/linux/releases/14/Fedora/x86_64/os",
+ require => Exec['pulp-auth']}
+
+ exec{'pulp-f14-x86-64-repo-sync':
+ command => "/usr/bin/pulp-admin repo sync --id f14-x86_64",
+ logoutput => true,
+ require => Exec['pulp-f14-x86-64-repo-create']}
+}
+
+class aeolus::pulp::disabled {
+ service { 'pulp-server':
+ ensure => 'stopped',
+ enable => false,
+ hasstatus=> true
+ }
+}
diff --git a/recipes/aeolus_recipe/templates/pulp-client.conf
b/recipes/aeolus_recipe/templates/pulp-client.conf
new file mode 100755
index 0000000..7c990e8
--- /dev/null
+++ b/recipes/aeolus_recipe/templates/pulp-client.conf
@@ -0,0 +1,49 @@
+# The pulp server configuration
+# host : The pulp server
+# port : The port providing the RESTful API.
+# scheme : The protocol.
+# interval : The agent update interval
+[server]
+host = <%= fqdn %>
+port = 443
+scheme = https
+path = /pulp/api
+interval = 240
+
+# Client configuration
+# reboot_schedule : Time in minutes or 'now' before system is scheduled for
reboot
+# when user requests a reboot for applicable errata.
+# assumeyes : Uncomment this to override this value. Assumes that install performs
all the suggested actions such as reboot on successful install;
+# import_gpg_keys : automatically import gpg keys if available during remote package
installs
+[client]
+reboot_schedule = 3
+import_gpg_keys = False
+#assumeyes = False
+repo_file = /etc/yum.repos.d/pulp.repo
+mirror_list_dir = /etc/yum.repos.d
+gpg_keys_dir = /etc/pki/pulp-gpg-keys
+
+# heartbeat
+# interval in seconds
+[heartbeat]
+seconds=10
+
+# messaging
+# scheme: (tcp|ssl)
+# port: broker port
+# cacert: the CA certificate (PEM) to verify the server.
+# clientcert: The client (PEM) key & certificate.
+[messaging]
+scheme = tcp
+port = 5672
+cacert =
+clientcert =
+
+
+# Content distribution options
+# baseurl : The content base url
+# keyurl : The gpg key base url
+[cds]
+baseurl =
https://localhost/pulp/repos
+keyurl =
http://localhost/pulp/gpg
+ksurl =
http://localhost/pulp/ks
diff --git a/recipes/aeolus_recipe/templates/pulp-temp-fix-server.py
b/recipes/aeolus_recipe/templates/pulp-temp-fix-server.py
new file mode 100644
index 0000000..bf6ba61
--- /dev/null
+++ b/recipes/aeolus_recipe/templates/pulp-temp-fix-server.py
@@ -0,0 +1,302 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2011 Red Hat, Inc.
+#
+# This software is licensed to you under the GNU General Public License,
+# version 2 (GPLv2). There is NO WARRANTY for this software, express or
+# implied, including the implied warranties of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
+# along with this software; if not, see
+#
http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+#
+# Red Hat trademarks are not licensed under GPLv2. No permission is
+# granted to use or replicate Red Hat trademarks that are incorporated
+# in this software or its documentation.
+
+import base64
+import httplib
+import locale
+import os
+import sys
+import urllib
+from gettext import gettext as _
+
+try:
+ import json
+except ImportError:
+ import simplejson as json
+
+from M2Crypto import SSL, httpslib
+
+from pulp.client.logutil import getLogger
+
+# current active server -------------------------------------------------------
+
+active_server = None
+
+
+def set_active_server(server):
+ global active_server
+ assert isinstance(server, Server)
+ active_server = server
+
+# base server class -----------------------------------------------------------
+
+class ServerRequestError(Exception):
+ """
+ Exception to indicate a less than favorable response from the server.
+ The arguments are [0] the response status as an integer and
+ [1] the response message as a dict, if we managed to decode from json,
+ or a str if we didn't [2] potentially a traceback, if the server response
+ was a python error, otherwise it will be None
+ """
+ pass
+
+
+class Bytes(str):
+ """
+ Binary (non-json) PUT/POST request body wrapper.
+ """
+ pass
+
+
+class Server(object):
+ """
+ Base server class.
+ @ivar host: host name of the pulp server
+ @ivar port: port the pulp server is listening on (443)
+ @ivar protocol: protocol the pulp server is using (http, https)
+ @ivar path_prefix: mount point of the pulp api (/pulp/api)
+ @ivar headers: dictionary of http headers to send in requests
+ """
+
+ def __init__(self, host, port=80, protocol='http', path_prefix=''):
+ assert protocol in ('http', 'https')
+
+ self.host = host
+ self.port = port
+ self.protocol = protocol
+ self.path_prefix = path_prefix
+ self.headers = {}
+
+ # credentials setters -----------------------------------------------------
+
+ def set_basic_auth_credentials(self, username, password):
+ """
+ Set username and password credentials for http basic auth
+ @type username: str
+ @param username: username
+ @type password: str
+ @param password: password
+ """
+ raise NotImplementedError('base server class method called')
+
+ def set_ssl_credentials(self, certfile, keyfile):
+ """
+ Set ssl certificate and public key credentials
+ @type certfile: str
+ @param certfile: absolute path to the certificate file
+ @type keyfile: str
+ @param keyfile: absolute path to the public key file
+ @raise RuntimeError: if either of the files cannot be found or read
+ """
+ raise NotImplementedError('base server class method called')
+
+ def has_credentials_set(self):
+ raise NotImplementedError('base server class method called')
+
+ # request methods ---------------------------------------------------------
+
+ def DELETE(self, path):
+ """
+ Send a DELETE request to the pulp server.
+ @type path: str
+ @param path: path of the resource to delete
+ @rtype: (int, dict or None or str)
+ @return: tuple of the http response status and the response body
+ @raise ServerRequestError: if the request fails
+ """
+ raise NotImplementedError('base server class method called')
+
+ def GET(self, path, queries=()):
+ """
+ Send a GET request to the pulp server.
+ @type path: str
+ @param path: path of the resource to get
+ @type queries: dict or iterable of tuple pairs
+ @param queries: dictionary of iterable of key, value pairs to send as
+ query parameters in the request
+ @rtype: (int, dict or None or str)
+ @return: tuple of the http response status and the response body
+ @raise ServerRequestError: if the request fails
+ """
+ raise NotImplementedError('base server class method called')
+
+ def HEAD(self, path):
+ """
+ Send a HEAD request to the pulp server.
+ @type path: str
+ @param path: path of the resource to check
+ @rtype: (int, dict or None or str)
+ @return: tuple of the http response status and the response body
+ @raise ServerRequestError: if the request fails
+ """
+ raise NotImplementedError('base server class method called')
+
+ def POST(self, path, body=None):
+ """
+ Send a POST request to the pulp server.
+ @type path: str
+ @param path: path of the resource to post to
+ @type body: dict or None
+ @param body: (optional) dictionary for json encoding of post parameters
+ @rtype: (int, dict or None or str)
+ @return: tuple of the http response status and the response body
+ @raise ServerRequestError: if the request fails
+ """
+ raise NotImplementedError('base server class method called')
+
+ def PUT(self, path, body):
+ """
+ Send a PUT request to the pulp server.
+ @type path: str
+ @param path: path of the resource to put
+ @type body: dict
+ @param body: dictionary for json encoding of resource
+ @rtype: (int, dict or None or str)
+ @return: tuple of the http response status and the response body
+ @raise ServerRequestError: if the request fails
+ """
+ raise NotImplementedError('base server class method called')
+
+# pulp server class -----------------------------------------------------------
+
+class PulpServer(Server):
+ """
+ Pulp server connection class.
+ """
+
+ def __init__(self, host, port=443, protocol='https',
path_prefix='/pulp/api'):
+ super(PulpServer, self).__init__(host, port, protocol, path_prefix)
+
+ default_locale = locale.getdefaultlocale()[0]
+ if default_locale:
+ default_locale = default_locale.lower().replace('_', '-')
+ else:
+ default_locale = "en-us"
+
+ headers = {'Accept': 'application/json',
+ 'Accept-Language': default_locale,
+ 'Content-Type': 'application/json'}
+ self.headers.update(headers)
+
+ self._log = getLogger('pulp')
+
+ self.__certfile = None
+ self.__keyfile = None
+
+ # protected server connection methods -------------------------------------
+
+ def _http_connection(self):
+ return httplib.HTTPConnection(self.host, self.port)
+
+ def _https_connection(self):
+ # make sure that passed in username and password overrides cert/key auth
+ if None in (self.__certfile, self.__keyfile) or \
+ 'Authorization' in self.headers:
+ return httplib.HTTPSConnection(self.host, self.port)
+ ssl_context = SSL.Context('sslv3')
+ ssl_context.load_cert(self.__certfile, self.__keyfile)
+ #print >> sys.stderr, 'making connection with: %s, %s' %
(self.__certfile,
+ # self.__keyfile)
+ return httpslib.HTTPSConnection(self.host,
+ self.port,
+ ssl_context=ssl_context)
+
+ def _connect(self):
+ # make an appropriate connection to the pulp server and cache it
+ if self.protocol == 'http':
+ return self._http_connection()
+ else:
+ return self._https_connection()
+
+ # protected request utilities ---------------------------------------------
+
+ def _build_url(self, path, queries=()):
+ # build the request url from the path and queries dict or tuple
+ if not path.startswith(self.path_prefix):
+ path = '/'.join((self.path_prefix, path))
+ # make sure the path is ascii and uses appropriate characters
+ path = urllib.quote(str(path))
+ queries = urllib.urlencode(queries)
+ if queries:
+ path = '?'.join((path, queries))
+ return path
+
+ def _request(self, method, path, queries=(), body=None):
+ # make a request to the pulp server and return the response
+ # NOTE this throws a ServerRequestError if the request did not succeed
+ connection = self._connect()
+ url = self._build_url(path, queries)
+ if not isinstance(body, (type(None), Bytes,)):
+ body = json.dumps(body)
+ self._log.debug('sending %s request to %s' % (method, url))
+ #print >> sys.stderr, 'sending %s request to %s' % (method, url)
+ connection.request(method, url, body=body, headers=self.headers)
+ response = connection.getresponse()
+ response_body = response.read()
+ try:
+ response_body = json.loads(response_body)
+ except:
+ pass
+ if response.status >= 300:
+ # if the server has responded with a python traceback
+ # try to split it out
+ if isinstance(response_body, basestring) and \
+ response_body.startswith('Traceback'):
+ traceback, message = response_body.strip().rsplit('\n', 1)
+ raise ServerRequestError(response.status, message, traceback)
+ raise ServerRequestError(response.status, response_body, None)
+ return (response.status, response_body)
+
+ def _encoded(self, body):
+ if body is None:
+ return body
+
+ # credentials setters -----------------------------------------------------
+
+ def set_basic_auth_credentials(self, username, password):
+ raw = ':'.join((username, password))
+ encoded = base64.encodestring(raw)[:-1]
+ self.headers['Authorization'] = 'Basic ' + encoded
+
+ def set_ssl_credentials(self, certfile, keyfile):
+ if not os.access(certfile, os.R_OK):
+ raise RuntimeError(_('certificate file %s does not exist or cannot be
read')
+ % certfile)
+ if not os.access(keyfile, os.R_OK):
+ raise RuntimeError(_('key file %s does not exist or cannot be read')
+ % keyfile)
+ self.__certfile = certfile
+ self.__keyfile = keyfile
+
+ def has_credentials_set(self):
+ return 'Authorization' in self.headers or \
+ None not in (self.__certfile, self.__keyfile)
+
+ # request methods ---------------------------------------------------------
+
+ def DELETE(self, path):
+ return self._request('DELETE', path)
+
+ def GET(self, path, queries=()):
+ return self._request('GET', path, queries)
+
+ def HEAD(self, path):
+ return self._request('HEAD', path)
+
+ def POST(self, path, body=None):
+ return self._request('POST', path, body=body)
+
+ def PUT(self, path, body):
+ return self._request('PUT', path, body=body)
diff --git a/recipes/aeolus_recipe/templates/pulp.conf
b/recipes/aeolus_recipe/templates/pulp.conf
new file mode 100644
index 0000000..ef34eaf
--- /dev/null
+++ b/recipes/aeolus_recipe/templates/pulp.conf
@@ -0,0 +1,119 @@
+# Server options
+#
+# server_name: server hostname(protocol defaults to https)
+# relative_url: the relative url at which repos are exposed to the clients
+# key_url: the relative url at which gpg keys are exposed to clients
+# default_login: default admin username for your pulp server
+# default_password: default password for admin
+# Highly recommend changing the default_password with "pulp-admin user update"
+#
+[server]
+server_name: <%= fqdn %>
+relative_url: /pulp/repos
+key_url: /pulp/gpg
+default_login: admin
+default_password: admin
+
+# Messaging options.
+#
+# url: the broker url.
+# cacert: path to PEM encoded CA certificate file
+# clientcert: path to PEM encoded file containing both
+# the private key and certificate.
+#
+# The url has form: <transport>://<host>:<port> where
+# transport can be (tcp|ssl). When ssl is specified,
+# cacert and clientcert must be specified.
+
+[messaging]
+url: tcp://localhost:5672
+cacert: /etc/pki/qpid/ca/ca.crt
+clientcert: /etc/pki/qpid/client/client.pem
+
+#
+# AMQP event processing
+#
+[events]
+send_enabled: false
+recv_enabled: false
+
+# Configures aspects of the pulp web server security.
+#
+# cacert: full path to the CA certificate that will be used to sign
+# consumer and admin identification certificates. This MUST match
+# the value of SSLCACertificateFile in /etc/httpd/conf.d/pulp.conf.
+# cakey: full path to the private key for the CA certificate
+#
+
+[security]
+cacert: /etc/pki/pulp/ca.crt
+cakey: /etc/pki/pulp/ca.key
+# oauth_key: string key to enable OAuth style authentication
+# oauth_secret: string shared secret that can be used for OAuth style authentication
+# For more info see:
https://fedorahosted.org/pulp/wiki/Authentication
+
+[auditing]
+events_file: /var/log/pulp/events.log
+lifetime: 90
+backups: 4
+
+# Configuration for storage of consumer history
+#
+# lifetime: length in days - consumer history entries older than this
+# will be purged; setting this to -1 will disable history purging
+[consumer_history]
+lifetime: 180
+
+[logs]
+qpid_log_level: info
+level: info
+pulp_file: /var/log/pulp/pulp.log
+grinder_file: /var/log/pulp/grinder.log
+
+[rhn]
+# using less than 5 threads can cause issues with progress feed back
+threads: 5
+fetch_all_packages: false
+remove_old_packages: false
+cert_file: /etc/sysconfig/rhn/entitlement-cert.xml
+systemid_file: /etc/sysconfig/rhn/systemid
+
+[yum]
+threads: 3
+# True/False to flag if we should remove older rpms
+remove_old_packages: false
+# Integer to specify how many old packages to keep.
+# Only used if 'removeold' is set to True
+num_old_pkgs_keep: 2
+# Uncomment below to set a bandwidth limit in KB/sec for downloading
+# Only used if 'removeold' is set to True
+num_old_pkgs_keep: 2
+# Uncomment below to set a bandwidth limit in KB/sec for downloading
+# 0 represents unlimited
+# limit_in_KB: 500
+# Uncomment the below section with appropriate values for proxy configuration
+# proxy_url:
+# proxy_port:
+# proxy_user:
+# proxy_pass:
+
+[repos]
+content_url:
https://cdn.redhat.com/
+use_entitlement_certs = false
+default_to_published: true
+
+[database]
+# automatically upgrade the database when the data model changes
+name: pulp_database
+# comma separated list of URIs to pass to pymongo
+seeds: localhost
+
+# Uncomment the below section with appropriate values, to use an external ldap for
+# user authentication instead of pulp.
+#[ldap]
+#uri: ldap://localhost
+#base: dc=localhost
+
+[cds]
+# messaging timeout for sync. <initial>:<duration>
+sync_timeout = 10:7200
--
1.7.4.4