Package pulp :: Package client :: Package core :: Module core_repo
[hide private]
[frames] | no frames]

Source Code for Module pulp.client.core.core_repo

  1  #!/usr/bin/python 
  2  # 
  3  # Pulp Repo management module 
  4  # 
  5  # Copyright (c) 2010 Red Hat, Inc. 
  6  # 
  7  # This software is licensed to you under the GNU General Public License, 
  8  # version 2 (GPLv2). There is NO WARRANTY for this software, express or 
  9  # implied, including the implied warranties of MERCHANTABILITY or FITNESS 
 10  # FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 
 11  # along with this software; if not, see 
 12  # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 
 13  # 
 14  # Red Hat trademarks are not licensed under GPLv2. No permission is 
 15  # granted to use or replicate Red Hat trademarks that are incorporated 
 16  # in this software or its documentation. 
 17  # 
 18   
 19  import os 
 20  import sys 
 21  import time 
 22  import base64 
 23   
 24  import pulp.client.utils as utils 
 25  import pulp.client.constants as constants 
 26  from pulp.client.core.basecore import BaseCore, systemExit 
 27  from pulp.client.connection import RepoConnection, RestlibException 
 28  from pulp.client.logutil import getLogger 
 29  from pulp.client.config import Config 
 30  CFG = Config() 
 31   
 32  import gettext 
 33  _ = gettext.gettext 
 34  log = getLogger(__name__) 
 35   
36 -class repo(BaseCore):
37 - def __init__(self, actions=None):
38 usage = "repo [OPTIONS]" 39 shortdesc = "repository specifc actions to pulp server." 40 desc = "" 41 self.name = "repo" 42 self.actions = actions or {"create" : "Create a repo", 43 "update" : "Update a repo", 44 "list" : "List available repos", 45 "delete" : "Delete a repo", 46 "sync" : "Sync data to this repo from the feed", 47 "cancel_sync": "Cancel a running sync", 48 "upload" : "Upload package(s) to this repo", 49 "schedules" : "List all repo schedules", } 50 BaseCore.__init__(self, "repo", usage, shortdesc, desc)
51
52 - def load_server(self):
53 self.pconn = RepoConnection(host=CFG.server.host or "localhost", 54 port=CFG.server.port or 443, 55 username=self.username, 56 password=self.password, 57 cert_file=self.cert_filename, 58 key_file=self.key_filename)
59 - def generate_options(self):
60 self.action = self._get_action() 61 if self.action == "create": 62 usage = "repo create [OPTIONS]" 63 self.setup_option_parser(usage, "", True) 64 self.parser.add_option("--id", dest="id", 65 help="Repository Id") 66 self.parser.add_option("--name", dest="name", 67 help="Common repository name") 68 self.parser.add_option("--arch", dest="arch", 69 help="Package arch the repo should support.") 70 self.parser.add_option("--feed", dest="feed", 71 help="Url feed to populate the repo") 72 self.parser.add_option("--cacert", dest="cacert", 73 help="Path location to CA Certificate.") 74 self.parser.add_option("--cert", dest="cert", 75 help="Path location to Entitlement Certificate.") 76 self.parser.add_option("--key", dest="key", 77 help="Path location to Entitlement Cert Key.") 78 self.parser.add_option("--schedule", dest="schedule", 79 help="Schedule for automatically synchronizing the repository") 80 self.parser.add_option("--symlinks", action="store_true", dest="symlinks", 81 help="Use symlinks instead of copying bits locally. \ 82 Applicable for local syncs") 83 if self.action == "sync": 84 usage = "repo sync [OPTIONS]" 85 self.setup_option_parser(usage, "", True) 86 self.parser.add_option("--id", dest="id", 87 help="Repository Id") 88 self.parser.add_option("--timeout", dest="timeout", 89 help="Sync Timeout") 90 if self.action == "cancel_sync": 91 usage = "repo cancel_sync [OPTIONS]" 92 self.setup_option_parser(usage, "", True) 93 self.parser.add_option("--id", dest="id", 94 help="Repository Id") 95 self.parser.add_option("--taskid", dest="taskid", 96 help="Task ID") 97 if self.action == "delete": 98 usage = "repo delete [OPTIONS]" 99 self.setup_option_parser(usage, "", True) 100 self.parser.add_option("--id", dest="id", 101 help="Repository Id") 102 if self.action == "list": 103 usage = "repo list [OPTIONS]" 104 self.setup_option_parser(usage, "", True) 105 if self.action == "upload": 106 usage = "repo upload [OPTIONS] <package>" 107 self.setup_option_parser(usage, "", True) 108 self.parser.add_option("--id", dest="id", 109 help="Repository Id") 110 self.parser.add_option("--dir", dest="dir", 111 help="Process packages from this directory") 112 if self.action == "schedules": 113 usage = "repo schedules" 114 self.setup_option_parser(usage, "", True)
115
116 - def _do_core(self):
117 if self.action == "create": 118 self._create() 119 if self.action == "list": 120 self._list() 121 if self.action == "sync": 122 self._sync() 123 if self.action == "cancel_sync": 124 self._cancel_sync() 125 if self.action == "delete": 126 self._delete() 127 if self.action == "upload": 128 self._upload() 129 if self.action == "schedules": 130 self._schedules()
131
132 - def _create(self):
133 if not self.options.id: 134 print("repo id required. Try --help") 135 sys.exit(0) 136 if not self.options.name: 137 self.options.name = self.options.id 138 if not self.options.arch: 139 self.options.arch = "noarch" 140 141 symlinks = False 142 if self.options.symlinks: 143 symlinks = self.options.symlinks 144 145 cert_data = None 146 if self.options.cacert and self.options.cert and self.options.key: 147 cert_data = {"ca" : utils.readFile(self.options.cacert), 148 "cert" : utils.readFile(self.options.cert), 149 "key" : utils.readFile(self.options.key)} 150 151 try: 152 repo = self.pconn.create(self.options.id, self.options.name, \ 153 self.options.arch, self.options.feed, \ 154 symlinks, self.options.schedule, cert_data=cert_data) 155 print _(" Successfully created Repo [ %s ]" % repo['id']) 156 except RestlibException, re: 157 log.error("Error: %s" % re) 158 systemExit(re.code, re.msg) 159 except Exception, e: 160 log.error("Error: %s" % e) 161 systemExit(e.code, e.msg)
162
163 - def _list(self):
164 try: 165 repos = self.pconn.repositories() 166 if not len(repos): 167 print _("No repos available to list") 168 sys.exit(0) 169 print """+-------------------------------------------+\n List of Available Repositories \n+-------------------------------------------+""" 170 for repo in repos: 171 #repo["packages"] = repo["packages"] 172 print constants.AVAILABLE_REPOS_LIST % (repo["id"], repo["name"], 173 repo["source"], repo["arch"], 174 repo["sync_schedule"], repo["packages"]) 175 except RestlibException, re: 176 log.error("Error: %s" % re) 177 systemExit(re.code, re.msg) 178 except Exception, e: 179 log.error("Error: %s" % e) 180 raise
181
182 - def _sync(self):
183 if not self.options.id: 184 print("repo id required. Try --help") 185 sys.exit(0) 186 try: 187 task_object = self.pconn.sync(self.options.id, self.options.timeout) 188 state = "waiting" 189 print "Task created with ID::", task_object['id'] 190 while state not in ["finished", "error", 'timed out', 'canceled']: 191 time.sleep(5) 192 status = self.pconn.sync_status(task_object['status_path']) 193 if status is None: 194 raise SyncError(_('No sync for repository [%s] found') % self.options.id) 195 state = status['state'] 196 print "Sync Status::", state 197 packages = self.pconn.packages(self.options.id) 198 pkg_count = 0 199 if packages: 200 pkg_count = len(packages) 201 if state == "error": 202 raise SyncError(status['traceback'][-1]) 203 else: 204 print _(" Sync Successful. Repo [ %s ] now has a total of [ %s ] packages" % (self.options.id, pkg_count)) 205 except RestlibException, re: 206 log.info("REST Error.", exc_info=True) 207 systemExit(re.code, re.msg) 208 except SyncError, se: 209 log.info("Sync Error: ", exc_info=True) 210 systemExit("Error : %s" % se) 211 except Exception, e: 212 log.error("General Error: %s" % e) 213 raise
214
215 - def _cancel_sync(self):
216 if not self.options.id: 217 print("repo id required. Try --help") 218 sys.exit(0) 219 if not self.options.taskid: 220 print("task id required. Try --help") 221 sys.exit(0) 222 try: 223 repos = self.pconn.cancel_sync(self.options.id, self.options.taskid) 224 print _(" Sync task %s cancelled") % self.options.taskid 225 except RestlibException, re: 226 log.error("Error: %s" % re) 227 systemExit(re.code, re.msg) 228 except Exception, e: 229 log.error("Error: %s" % e) 230 raise
231
232 - def _delete(self):
233 if not self.options.id: 234 print("repo id required. Try --help") 235 sys.exit(0) 236 try: 237 self.pconn.delete(id=self.options.id) 238 print _(" Successful deleted Repo [ %s ] " % self.options.id) 239 except RestlibException, re: 240 print _(" Deleted operation failed on Repo [ %s ] " % \ 241 self.options.id) 242 log.error("Error: %s" % re) 243 sys.exit(-1) 244 except Exception, e: 245 print _(" Deleted operation failed on Repo [ %s ]. " % \ 246 self.options.id) 247 log.error("Error: %s" % e) 248 sys.exit(-1)
249
250 - def _upload(self):
251 (self.options, files) = self.parser.parse_args() 252 # ignore the command and pick the files 253 files = files[2:] 254 if not self.options.id: 255 print("repo id required. Try --help") 256 sys.exit(0) 257 if self.options.dir: 258 files += utils.processDirectory(self.options.dir, "rpm") 259 if not files: 260 print("Need to provide atleast one file to perform upload") 261 sys.exit(0) 262 uploadinfo = {} 263 uploadinfo['repo'] = self.options.id 264 for frpm in files: 265 try: 266 pkginfo = utils.processRPM(frpm) 267 except FileError, e: 268 print('Error: %s' % e) 269 continue 270 if not pkginfo.has_key('nvrea'): 271 print("Package %s is Not an RPM Skipping" % frpm) 272 continue 273 pkgstream = base64.b64encode(open(frpm).read()) 274 try: 275 status = self.pconn.upload(self.options.id, pkginfo, pkgstream) 276 if status: 277 print _(" Successful uploaded [%s] to Repo [ %s ] " % (pkginfo['pkgname'], self.options.id)) 278 else: 279 print _(" Failed to Upload %s to Repo [ %s ] " % self.options.id) 280 except RestlibException, re: 281 log.error("Error: %s" % re) 282 raise #continue 283 except Exception, e: 284 log.error("Error: %s" % e) 285 raise #continue
286
287 - def _schedules(self):
288 print("""+-------------------------------------+\n Available Repository Schedules \n+-------------------------------------+""") 289 290 schedules = self.pconn.all_schedules() 291 for id in schedules.keys(): 292 print(constants.REPO_SCHEDULES_LIST % (id, schedules[id]))
293 294
295 -class FileError(Exception):
296 pass
297
298 -class SyncError(Exception):
299 pass
300