def runCommand(self, handle, argSet, args): ui = handle.ui message = argSet.pop('message', None) listTypes = argSet.pop('list', False) fromFile = argSet.pop('from-file', None) toFile = argSet.pop('to-file', None) if listTypes: ui.write('Available image definition types: %s' % ', '.join(IMAGEDEF_SPECS)) return if fromFile: handle.DescriptorConfig.readConfig(fromFile) _, selectedType, arch = self.requireParameters( args, expected=['TYPE', 'ARCH']) imageType = IMAGEDEF_SPECS.get(selectedType) if not imageType: raise errors.PluginError( "No such image type '%s'. Valid image types are: %s" % (selectedType, ', '.join(sorted(IMAGEDEF_SPECS)))) if arch not in ['x86', 'x86_64']: raise errors.PluginError( "No such architecture '%s'. Valid architectures are: x86 and" " x86_64" % arch) handle.CreateImageDef.create(imageType, arch, message) if toFile: handle.DescriptorConfig.writeConfig(toFile)
def _createJob(self, action_type, image_name, target_name, doLaunch): rb = self.handle.facade.rbuilder images = self.getImages(image_name) target = rb.getTargets(name=target_name) if not target: raise errors.PluginError("No target matching '%s'" % target_name) target = target[0] if target.is_configured == 'false': raise errors.PluginError( ("Target '{0}' is not configured. Try" " running \"rbuild edit target '{0}'\" or contacting" " your rbuilder administrator.").format(target.name)) if target.credentials_valid == 'false': raise errors.PluginError( ("Target '{0}' does not have valid" " credentials. Try running \"rbuild edit target '{0}'\"" " and updating your credentials.").format(target.name)) image, action = self._getAction(images, target, action_type) ddata = self.handle.DescriptorConfig.createDescriptorData( fromStream=action.descriptor) doc = xobj.Document() doc.job = job = xobj.XObj() job.job_type = action._root.job_type job.descriptor = action._root.descriptor job.descriptor_data = xobj.parse(ddata.toxml()).descriptor_data if doLaunch: return image.jobs.append(doc)
def runCommand(self, handle, argSet, args): ui = handle.ui rb = handle.facade.rbuilder message = argSet.pop('message', None) fromFile = argSet.pop('from-file', None) toFile = argSet.pop('to-file', None) if fromFile: handle.DescriptorConfig.readConfig(fromFile) _, type, arch = self.requireParameters(args, expected=['TYPE', 'ARCH']) imageType = [i for i in rb.getImageTypes() if i.name == type] if not imageType: raise errors.PluginError( "No such image type '%s'." " Run `rbuild list imagetypes` to see valid image types" % type) imageType = imageType[0] if arch not in ['x86', 'x86_64']: raise errors.PluginError( "No such architecture '%s'. Valid architectures are: x86 and" " x86_64" % arch) handle.ImageDefs.create(imageType, arch, message) if toFile: handle.DescriptorConfig.writeConfig(toFile)
def shadowPackage(self, packageName): conaryFacade = self.handle.facade.conary productStore = self.handle.productStore origName, version, flavor = conaryFacade.parseTroveSpec(packageName) package = None if version: package = self._getRemotePackage(origName, version) if package is None: raise errors.PluginError( '%s:source does not exist on label %s.' % \ (origName, version)) else: package = self._getUpstreamPackage(packageName) if package is None: # FIXME: since we shadow only source, why care about binary? raise errors.PluginError( 'cannot shadow %s: no upstream binary' % packageName) name, version, flavor = package currentLabel = productStore.getActiveStageLabel() conaryFacade.shadowSourceForBinary(name, version, flavor, currentLabel) targetDir = self.checkoutPackage(origName) self.handle.ui.info('Shadowed package %r in %r', packageName, self._relPath(os.getcwd(), targetDir))
def wrapper(*args, **kw): 'Decorator for methods that require HOME env variable to be set' if 'HOME' in os.environ: if not os.path.isdir(os.environ['HOME']): raise errors.PluginError( 'The HOME environment variable references' ' "%s" which does not exist') return func(*args, **kw) raise errors.PluginError('The HOME environment variable must be set')
def create(self, user_name, full_name, email, password=None, external_auth=False, is_admin=False, can_create=True): '''Create a rbuilder user :param user_name: login name for user :type user_name: str :param full_name: full name of the user :type full_name: str :param email: user's email address :type email: str :param password: user's password, if not using external authentication :type password: str :param external_auth: whether to use external auth, must not be True if password is provided, default False :type external_auth: bool :param is_admin: is this an admin user, default False :type is_admin: bool :param can_create: can this user create resources, default True :type can_create: bool :raises: rbuild.errors.PluginError ''' if external_auth and password: raise errors.PluginError('Cannot use a password with external' ' authentication') if not external_auth and not password: raise errors.PluginError('Must provide a password if not using' ' external authentication') if is_admin and not self.handle.facade.rbuilder.isAdmin(): raise errors.UnauthorizedActionError('grant admin privilege') # create the user xml document user_doc = xobj.Document() user_doc.user = user = xobj.XObj() user.user_name = user_name user.full_name = full_name user.email = email if password is not None: user.password = password user.external_auth = external_auth user.is_admin = is_admin user.can_create = can_create # POST the new user client = self.handle.facade.rbuilder._getRbuilderRESTClient() client.api.users.append(user_doc)
def _getProductStage(self): try: product = self.handle.product.getProductShortname() baseLabel = self.handle.product.getBaseLabel() except AttributeError: raise errors.PluginError( 'Current directory is not part of a product.\n' 'To initialize a new product directory, use "rbuild init"') try: stage = self.handle.productStore.getActiveStageName() except errors.RbuildError: raise errors.PluginError( 'Current directory is not a product stage.') return (product, baseLabel, stage)
def _getJobFromNames(handle, packageList): """ Build everything in C{packageList} without a rebuild and without recursing into the image group. """ packageRecipes, groupRecipes = handle.productStore.getEditedRecipeDicts() flavors = set(x[1] for x in handle.productStore.getGroupFlavors()) contexts = handle.facade.rmake._getRmakeContexts() if not flavors: raise errors.PluginError("no image flavors defined; " "don't know what to build") toBuild = [] for name in packageList: if name in packageRecipes: name = packageRecipes[name] elif name in groupRecipes: name = groupRecipes[name] for flavor in flavors: context = contexts[flavor] toBuild.append('%s{%s}' % (name, context)) return handle.facade.rmake.createBuildJobForStage(toBuild, recurse=False, rebuild=False, useLocal=True)
def showGroupStatus(self): jobId = self.handle.productStore.getGroupJobId() if not jobId: raise errors.PluginError('No groups have been built' ' in this environment') self.handle.Show.showJobStatus(jobId) return jobId
def runCommand(self, handle, argSet, args): watch = not argSet.pop('no-watch', False) commit = not argSet.pop('no-commit', False) recurse = argSet.pop('recurse', False) argSet.pop('no-recurse', False) # ignored, now the default refreshArg = argSet.pop('refresh', False) message = argSet.pop('message', None) success = True _, packageList, = self.requireParameters(args, allowExtra=True) handle.Build.checkStage() if not packageList: if refreshArg: handle.BuildPackages.refreshAllPackages() jobId = handle.BuildPackages.buildAllPackages() else: if refreshArg: handle.BuildPackages.refreshPackages(packageList) jobId = handle.BuildPackages.buildPackages(packageList, recurse) if watch and commit: success = handle.Build.watchAndCommitJob(jobId, message) elif watch: success = handle.Build.watchJob(jobId) if not success: raise errors.PluginError('Package build failed')
def watchJob(self, job): last_status = None while job.job_state.name in ['Queued', 'Running']: status = job.status_text if status != last_status: self.handle.ui.lineOutProgress(status.replace('%', '%%')) last_status = status time.sleep(1) job.refresh() if job.job_state.name == 'Failed': raise errors.PluginError(job.status_text) if self.handle.ui.outStream.isatty(): self.handle.ui.write() if job.job_type.name.startswith('launch'): for resource in job.created_resources: if hasattr(resource, 'networks'): msg = 'Created system %s with address' % resource.name if len(resource.networks) > 1: msg += 'es' msg += ': ' msg += ', '.join(n.dns_name for n in resource.networks) self.handle.ui.write(msg)
def showPackageStatus(self): jobId = self.handle.productStore.getPackageJobId() if not jobId: raise errors.PluginError( 'No packages have been built in this environment') self.handle.Show.showJobStatus(jobId) return jobId
def updateCurrentStage(self): """ Update all source packages in the current stage in the current product. """ stageName = self.handle.productStore.getActiveStageName() if not stageName: raise errors.PluginError('Could not find current stage') self.updateStages([stageName])
def createDescriptorData(self, fromStream=None): descr = self.descriptorClass(fromStream=fromStream) cb = self.callbackClass(self.handle.ui, self._config) try: ddata = descr.createDescriptorData(cb) except ConstraintsValidationError as e: raise errors.PluginError('\n'.join(m for m in e[0])) self._parseDescriptorData(ddata) return ddata
def _cancelImage(self, images): if not isinstance(images, list): images = [images] for image in images: if self._promptUser(image): job = self._getCancelBuildJob(image) if job and job.status_code != '200': raise errors.PluginError(job.status_text)
def derivePackage(self, packageName): ui = self.handle.ui upstreamLatest = self._getUpstreamPackage(packageName) if not upstreamLatest: raise errors.PluginError('cannot derive %s: no upstream binary' % packageName) targetDir = derive.derive(self.handle, upstreamLatest) ui.info('Derived %r in %r from %s=%s[%s]', packageName, targetDir, *upstreamLatest) ui.info('Edit the recipe to add your changes to the binary package.')
def _getAction(self, images, target, key): assert key in (self.DEPLOY, self.LAUNCH) for image in images: for action in image.actions: if key == action.key and target in action.name: return image, action raise errors.PluginError( 'Image cannot be %s on this target' % ('deployed' if key == self.DEPLOY else 'launched'))
def newPackage(self, packageName, message=None, template=None, factory=None): ui = self.handle.ui conaryFacade = self.handle.facade.conary productStore = self.handle.productStore currentLabel = productStore.getActiveStageLabel() targetDir = productStore.getCheckoutDirectory(packageName) existingPackage = self._getExistingPackage(packageName) if existingPackage: if existingPackage[1].isShadow(): confirmDetach = ui.getYn( '%s is shadowed on the current label.\n' 'Do you want to detach this package from its ' 'parent? (Y/N): ' % packageName) if not confirmDetach: return conaryFacade.detachPackage(existingPackage, '/' + currentLabel, message) ui.info('Detached package %s from its parent.' \ % packageName) else: raise errors.PluginError('\n'.join( ('This package already exists in the product.', 'Use "rbuild checkout %s" to checkout the existing ' 'package to modify its files, or give the new package ' 'a different name.' % packageName))) else: upstreamLatest = self._getUpstreamPackage(packageName) if upstreamLatest: ui.warning('Package %s exists upstream.' % packageName) confirmReplace = ui.getYn( 'Do you want to replace the upstream version? (Y/N):') if not confirmReplace: return if packageName.startswith('factory-'): # A package named 'factory-' is required to BE a factory factory = 'factory' elif (packageName.startswith('group-') and packageName.endswith('-appliance') and template is None): template = self.handle.getConfig().applianceTemplate conaryFacade.createNewPackage(packageName, currentLabel, targetDir=targetDir, template=template, factory=factory) ui.info('Created new package %r in %r', packageName, self._relPath(os.getcwd(), targetDir)) return
def runCommand(self, handle, argSet, args): ui = handle.ui try: pd = handle.product except AttributeError: raise errors.PluginError('Must be in an rbuild checkout') message = argSet.pop('message', None) listImageDefs = argSet.pop('list', False) fromFile = argSet.pop('from-file', None) toFile = argSet.pop('to-file', None) stageName = handle.productStore._currentStage if stageName: buildDefs = pd.getBuildsForStage(stageName) else: buildDefs = pd.getBuildDefinitions() if listImageDefs: ui.write('Available image defintions:\n %s' % '\n '.join(bd.name for bd in buildDefs)) return _, imageDefName = self.requireParameters(args, expected='NAME') if fromFile: handle.DescriptorConfig.readConfig(fromFile) buildDef = None for bd in buildDefs: if bd.name == imageDefName: buildDef = bd break if buildDef is None: raise errors.PluginError("Cound not find image definition '%s'" % imageDefName) handle.Edit.editImageDefinition(buildDef, message) if toFile: handle.DescriptorConfig.writeConfig(toFile)
def runCommand(self, handle, argSet, args): watch = not argSet.pop('no-watch', False) _, imageNames = self.requireParameters(args, allowExtra=True) if imageNames == []: imageNames = None jobId = handle.BuildImages.buildImages(imageNames) if watch: handle.Build.watchJob(jobId) if not handle.facade.rmake.isJobBuilt(jobId): raise errors.PluginError('Image build failed') handle.BuildImages.printImageUrlsForJob(jobId)
def _createRmakeJobForGroups(handle, groupList=None): allRecipes = handle.productStore.getEditedRecipeDicts() _, groupRecipes = allRecipes if groupList is not None: groupRecipes = dict(x for x in groupRecipes.items() if x[0] in groupList) if len(groupRecipes) < len(groupList): notFound = set(groupList) - set(groupRecipes) raise errors.PluginError( 'the following groups' ' were not found: %s' % ', '.join(sorted(notFound))) assert(len(groupRecipes) == len(groupList)) elif not groupRecipes: raise errors.PluginError( 'no groups are currently being edited - nothing to build') mainJob = _getJobBasedOnProductGroups(handle, groupRecipes) if mainJob is None: raise errors.PluginError('No groups found to build') return mainJob
def _getAction(self, images, target, key): assert key in (self.DEPLOY, self.LAUNCH) for image in images: if image.status != '300': continue for action in image.actions: if key == action.key and target.name in action.name: return image, action raise errors.PluginError("cannot %s %s" % (key.replace('_', ' '), target))
def runCommand(self, handle, argSet, args): lateCommit = argSet.pop('late-commit', False) workers = int(argSet.pop('workers', 30)) retries = int(argSet.pop('retries', 0)) _, pkgList = self.requireParameters(args, allowExtra=True) results = handle.MirrorBall.buildmany(pkgList, lateCommit=lateCommit, workers=workers, retries=retries) if not results: raise errors.PluginError('pacakges failed to build')
def _createRmakeJobForPackages(handle, packageList=None, recurse=True): if packageList and not recurse: return _getJobFromNames(handle, packageList) else: allRecipes = handle.productStore.getEditedRecipeDicts() packageRecipes, groupRecipes = allRecipes if packageList is not None: packageRecipes = dict(x for x in packageRecipes.items() if x[0] in packageList) if len(packageRecipes) < len(packageList): notFound = set(packageList) - set(packageRecipes) raise errors.PluginError('the following packages' ' were not found: %s' % ', '.join(sorted(notFound))) assert (len(packageRecipes) == len(packageList)) elif not packageRecipes: raise errors.PluginError( 'no packages are currently being edited - nothing to build') mainJob = groups._getJobBasedOnProductGroups(handle, groupRecipes, recurse=True) # overlay the main job with the recipes that are checked out. return _addInEditedPackages(handle, mainJob, packageRecipes)
def _getHandle(args): """ Search `args` for a handle. If the first item in `args` is a Plugin, then return the Plugin's handle. Else if the second item in `args` is a RbuildHandle, then return it. :param list args: list to search :return RbuildHandle: a handle """ if isinstance(args[0], Plugin): return args[0].handle elif isinstance(args[1], RbuildHandle): return args[1] else: raise errors.PluginError("Must wrap a plugin method or the runCommand" " method of a BaseCommand subclass")
def createTarget(self, targetType): ''' Create a target @param targetType: type of target to create @type targetType: string @return: configured target @rtype: rObj(target) ''' dc = self.handle.DescriptorConfig rb = self.handle.facade.rbuilder targetTypes = [t for t in rb.getTargetTypes() if t.name == targetType] if not targetTypes: raise errors.PluginError( "No such target type '%s'. Run `rbuild list targettypes` to" " see valid target types" % targetType) ttype = targetTypes[0] descriptor_xml = ttype.descriptor_create_target.read() currentValues = {} config_complete = False while not config_complete: ddata = dc.createDescriptorData(fromStream=descriptor_xml, defaults=currentValues) target = rb.createTarget(str(ttype.name), ddata) try: rb.configureTarget(target, ddata) config_complete = True except errors.RbuildError as e: name = target.name # delete target no matter what target.delete() self.handle.ui.warning(str(e)) if self.handle.ui.getYn("Edit {0} again?".format(name), default=False): # reprompt using current values currentValues = dict( (f.getName(), f.getValue()) for f in ddata.getFields()) dc.clearConfig() else: raise TargetNotCreated(name) return target
def runCommand(self, handle, argSet, args): watch = not argSet.pop('no-watch', False) commit = not argSet.pop('no-commit', False) message = argSet.pop('message', None) success = True _, groupList, = self.requireParameters(args, allowExtra=True) if not groupList: jobId = handle.BuildGroups.buildAllGroups() else: jobId = handle.BuildGroups.buildGroups(groupList) if watch and commit: success = handle.Build.watchAndCommitJob(jobId, message) elif watch: success = handle.Build.watchJob(jobId) if not success: raise errors.PluginError('Group build failed')
def checkoutPackageDefault(self, packageName, template=None, factory=None): existingPackage = self._getExistingPackage(packageName) if existingPackage: targetDir = self.checkoutPackage(packageName) self.handle.ui.info('Checked out existing package %r in %r', packageName, self._relPath(os.getcwd(), targetDir)) return targetDir upstreamLatest = self._getUpstreamPackage(packageName) if upstreamLatest: raise errors.PluginError('\n'.join( ('The upstream source provides a version of this package.', 'Please specify:', ' --shadow to shadow this package', ' --derive to derive from it', ' --new to replace it with a new version'))) self.newPackage(packageName, template=template, factory=factory)
def edit(self, targetName, targetType=None): dc = self.handle.DescriptorConfig rb = self.handle.facade.rbuilder ui = self.handle.ui target = rb.getTargets(name=targetName) if target: if len(target) > 1: if targetType: target = [ t for t in target if t.target_type.name == targetType ][0] else: ui.write('Ambiguous target name') response = ui.getChoice('Pick a target', pageSize=10, choices=[ '%s (%s)' % (t.name, t.target_type.name) for t in target ]) target = target[response] else: target = target[0] else: msg = "No target found with name '%s'" % targetName if targetType: msg = ' '.join([msg, "and type '%s'" % targetType]) raise errors.PluginError(msg) if rb.isAdmin(self.handle.getConfig().user[0]): currentValues = dict((e, getattr(target.target_configuration, e)) for e in target.target_configuration.elements) ttype = [ t for t in rb.getTargetTypes() if t.name == target.target_type.name ][0] ddata = dc.createDescriptorData( fromStream=ttype.descriptor_create_target.read(), defaults=currentValues, ) target = rb.configureTarget(target, ddata) self.configureTargetCredentials(target)
def runCommand(self, handle, argSet, args): ui = handle.ui rb = handle.facade.rbuilder if not argSet.get('project'): argSet['project'] = ui.getResponse( "Project name", validationFn=rb.isValidShortName) if not argSet.get('branch'): argSet['branch'] = ui.getResponse( "Branch name", validationFn=rb.isValidBranchName) argSet['description'] = ui.input("Branch description (optional): ") argSet['namespace'] = ui.input("Namespace (blank for default): ") platforms = rb.listPlatforms() if argSet.get('platform'): match = argSet['platform'].lower().strip() platformLabel = None for platform in platforms: for value in (platform.platformName, platform.label, platform.id): if value.lower().strip() == match: platformLabel = platform.label break if platformLabel is not None: break if platformLabel is None: raise errors.PluginError("No platform matching term '%s' " "was found" % (argSet['platform'], )) else: display = [ '%s - %s' % (x.platformName, x.label) for x in platforms ] response = ui.getChoice("Platform", display, "The following platforms are available:") platformLabel = platforms[response].label label = rb.createBranch( project=argSet['project'], name=argSet['branch'], platformLabel=platformLabel, namespace=argSet.get('namespace'), description=argSet.get('description', ''), ) ui.info("Created branch on label %s", label) ui.info("Type 'rbuild init %s %s' to begin working with it", argSet['project'], argSet['branch'])