1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import sys
19 from M2Crypto import SSL
20 import pulp.client.utils as utils
21 import pulp.client.constants as constants
22 from pulp.client.core.basecore import BaseCore, systemExit
23 from pulp.client.connection import ConsumerConnection, RestlibException
24 from pulp.client.repolib import RepoLib
25 from pulp.client.logutil import getLogger
26 from pulp.client.config import Config
27 from pulp.client.package_profile import PackageProfile
28 from pulp.client import json_utils
29 import urlparse
30 log = getLogger(__name__)
31 CFG = Config()
32
33 CONSUMERID = "/etc/pulp/consumer"
34
35
36 import gettext
37 _ = gettext.gettext
38
40 - def __init__(self, is_admin=True, actions=None):
41 usage = "consumer [OPTIONS]"
42 shortdesc = "consumer specific actions to pulp server."
43 desc = ""
44 self.name = "consumer"
45 self.actions = actions or {"delete" : "Delete the consumer",
46 "update" : "Update consumer profile",
47 "list" : "List of accessible consumer info",
48 "bind" : "Bind the consumer to listed repos",
49 "unbind" : "Unbind the consumer from repos",
50 "history" : "View the consumer history",
51 }
52 self.is_admin = is_admin
53 BaseCore.__init__(self, "consumer", usage, shortdesc, desc)
54 self.cconn = None
55
56
58 self.cconn = ConsumerConnection(host=CFG.server.host or "localhost",
59 port=443, username=self.username,
60 password=self.password,
61 cert_file=self.cert_filename,
62 key_file=self.key_filename)
63 self.repolib = RepoLib()
64
66 self.action = self._get_action()
67 if self.action == "create":
68 usage = "consumer create [OPTIONS]"
69 self.setup_option_parser(usage, "", True)
70 self.parser.add_option("--id", dest="id",
71 help="Consumer Identifier eg: foo.example.com")
72 self.parser.add_option("--description", dest="description",
73 help="consumer description eg: foo's web server")
74 self.parser.add_option("--server", dest="server",
75 help="The fully qualified hostname of the Pulp server you wish to create this consumer on")
76
77 if self.action == "update":
78 usage = "usage: %prog consumer update [OPTIONS]"
79 self.setup_option_parser(usage, "", True)
80 self.parser.add_option("--id", dest="id",
81 help="Consumer Identifier eg: foo.example.com")
82
83 if self.action == "bind":
84 usage = "usage: %prog consumer bind [OPTIONS]"
85 self.setup_option_parser(usage, "", True)
86 self.parser.add_option("--repoid", dest="repoid",
87 help="Repo Identifier")
88 if self.is_admin:
89 self.parser.add_option("--id", dest="id",
90 help="Consumer Identifier")
91
92 if self.action == "unbind":
93 usage = "usage: %prog consumer unbind [OPTIONS]"
94 self.setup_option_parser(usage, "", True)
95 self.parser.add_option("--repoid", dest="repoid",
96 help="Repo Identifier")
97 if self.is_admin:
98 self.parser.add_option("--id", dest="id",
99 help="Consumer Identifier")
100
101 if self.action == "list":
102 usage = "usage: %prog consumer list [OPTIONS]"
103 self.setup_option_parser(usage, "", True)
104
105 if self.action == "delete":
106 usage = "usage: %prog consumer delete [OPTIONS]"
107 self.setup_option_parser(usage, "", True)
108 if self.is_admin:
109 self.parser.add_option("--id", dest="id",
110 help="Consumer Identifier")
111
112 if self.action == "history":
113 usage = "usage: %prog consumer history [OPTIONS]"
114 self.setup_option_parser(usage, "", True)
115 self.parser.add_option('--event_type', dest='event_type',
116 help='Limits displayed history entries to the given type')
117 self.parser.add_option('--limit', dest='limit',
118 help='Limits displayed history entries to the given amount (must be greater than zero)')
119 self.parser.add_option('--sort', dest='sort',
120 help='Indicates the sort direction ("ascending" or "descending") based on the entry\'s timestamp')
121 self.parser.add_option('--start_date', dest='start_date',
122 help='Only return entries that occur after the given date (format: mm-dd-yyyy)')
123 self.parser.add_option('--end_date', dest='end_date',
124 help='Only return entries that occur before the given date (format: mm-dd-yyyy)')
125
141
143 if (not self.options.username and not self.options.password
144 and (len(self.args) > 0)):
145 print("username and password are required. Try --help")
146 sys.exit(1)
147 if not self.options.id:
148 print("consumer id required. Try --help")
149 sys.exit(0)
150 if not self.options.description:
151 self.options.description = self.options.id
152 if self.options.server:
153 CFG.server.host = self.options.server
154 CFG.write()
155 self.load_server()
156 try:
157 try:
158 consumer = self.cconn.create(self.options.id, self.options.description)
159 except SSL.Checker.WrongHost, wh:
160 print "ERROR: The server hostname you have configured in /etc/pulp/ does not match the"
161 print "hostname returned from the Pulp server you are connecting to. "
162 print ""
163 print "You have: [%s] configured but received: [%s] from the server." % (wh.expectedHost, wh.actualHost)
164 print ""
165 print "Either correct the host in /etc/pulp/ or specify --server=%s" % wh.actualHost
166 sys.exit(1)
167
168 cert_dict = self.cconn.certificate(self.options.id)
169 certificate = cert_dict['certificate']
170 key = cert_dict['private_key']
171 utils.writeToFile(CONSUMERID, consumer['id'])
172 utils.writeToFile(ConsumerConnection.CERT_PATH, certificate)
173 utils.writeToFile(ConsumerConnection.KEY_PATH, key)
174 pkginfo = PackageProfile().getPackageList()
175 self.cconn.profile(self.options.id, pkginfo)
176 print _(" Successfully created consumer [ %s ]" % consumer['id'])
177 except RestlibException, re:
178 log.error("Error: %s" % re)
179 systemExit(re.code, re.msg)
180 except Exception, e:
181 log.error("Error: %s", exc_info=True)
182 raise
183
197
199 try:
200 cons = self.cconn.consumer(self.getConsumer())
201 pkgs = " "
202 for pkg in cons['package_profile'].values():
203 for pkgversion in pkg:
204 pkgs += " " + utils.getRpmName(pkgversion)
205 cons['package_profile'] = pkgs
206 print """+-------------------------------------------+\n Consumer Information \n+-------------------------------------------+"""
207 for con in cons:
208 print constants.AVAILABLE_CONSUMER_INFO % \
209 (con["id"], con["description"], con["repoids"], con["package_profile"])
210 except RestlibException, re:
211 log.error("Error: %s" % re)
212 systemExit(re.code, re.msg)
213 except Exception, e:
214 log.error("Error: %s" % e)
215 raise
216
218 try:
219 cons = self.cconn.consumers()
220 baseurl = "%s://%s:%s" % (CFG.server.scheme, CFG.server.host, CFG.server.port)
221 for con in cons:
222 con['package_profile'] = urlparse.urljoin(baseurl, con['package_profile'])
223 print """+-------------------------------------------+\n Consumer Information \n+-------------------------------------------+"""
224 for con in cons:
225 print constants.AVAILABLE_CONSUMER_INFO % \
226 (con["id"], con["description"], con["repoids"], con["package_profile"])
227 except RestlibException, re:
228 log.error("Error: %s" % re)
229 systemExit(re.code, re.msg)
230 except Exception, e:
231 log.error("Error: %s" % e)
232 raise
233
235 consumerid = self.getConsumer()
236 if not self.options.repoid:
237 print("repo id required. Try --help")
238 sys.exit(0)
239 try:
240 self.cconn.bind(consumerid, self.options.repoid)
241 self.repolib.update()
242 print _(" Successfully subscribed consumer [%s] to repo [%s]" % (consumerid, self.options.repoid))
243 except RestlibException, re:
244 log.error("Error: %s" % re)
245 systemExit(re.code, re.msg)
246 except Exception, e:
247 log.error("Error: %s" % e)
248 raise
249
251 consumerid = self.getConsumer()
252 if not self.options.repoid:
253 print("repo id required. Try --help")
254 sys.exit(0)
255 try:
256 self.cconn.unbind(consumerid, self.options.repoid)
257 self.repolib.update()
258 print _(" Successfully unsubscribed consumer [%s] from repo [%s]" % (consumerid, self.options.repoid))
259 except RestlibException, re:
260 log.error("Error: %s" % re)
261 systemExit(re.code, re.msg)
262 except Exception, e:
263 log.error("Error: %s" % e)
264 raise
265
266
268 consumerid = self.getConsumer()
269 try:
270 self.cconn.delete(consumerid)
271 print _(" Successfully deleted consumer [%s]" % consumerid)
272 except RestlibException, re:
273 print _(" Deleted operation failed on consumer [ %s ] " % \
274 consumerid)
275 log.error("Error: %s" % re)
276 sys.exit(-1)
277 except Exception, e:
278 log.error("Error: %s" % e)
279 raise
280
281 - def _history(self):
282 consumerid = self.getConsumer()
283 try:
284
285 query_params = {
286 'event_type' : self.options.event_type,
287 'limit' : self.options.limit,
288 'sort' : self.options.sort,
289 'start_date' : self.options.start_date,
290 'end_date' : self.options.end_date,
291 }
292
293 results = self.cconn.history(consumerid, query_params)
294
295 print """+-------------------------------------------+\n Consumer History \n+-------------------------------------------+"""
296 for entry in results:
297
298
299 if constants.CONSUMER_HISTORY_EVENT_TYPES.has_key(entry['type_name']):
300 event_type = constants.CONSUMER_HISTORY_EVENT_TYPES[entry['type_name']]
301 else:
302 event_type = entry['type_name']
303
304
305 print constants.CONSUMER_HISTORY_ENTRY % \
306 (event_type, json_utils.parse_date(entry['timestamp']), entry['originator'])
307
308
309
310
311 if entry['type_name'] == 'repo_bound' or entry['type_name'] == 'repo_unbound':
312 print(constants.CONSUMER_HISTORY_REPO % (entry['details']['repo_id']))
313 if entry['type_name'] == 'package_installed' or entry['type_name'] == 'package_uninstalled':
314 print(constants.CONSUMER_HISTORY_PACKAGES)
315
316 for package_nvera in entry['details']['package_nveras']:
317 print(' %s' % package_nvera)
318
319 print('')
320
321 except RestlibException, re:
322 print _(" History retrieval failed for consumer [%s]" % consumerid)
323 sys.exit(-1)
324
326 if not self.options.id:
327 print("consumer id required. Try --help")
328 sys.exit(0)
329
330 return self.options.id
331