def _handle_list(self, args, session): """Implement list subcommand""" SQLType, schema, filter_attr = self.SQL_TYPE_MAP.get(args.type) assert SQLType, "Unkown type encountered, updated SQL_TYPE_MAP" report = Report(columns=schema) query = session.query(SQLType) # Handle filtering ################### filter_name = getattr(args, filter_attr) if filter_name != self.FILTER_ANY: sql_filter = self.SQL_FILTER_MAP.get(filter_name) assert sql_filter is not None, "Unknown sql filter, update SQL_FILTER_MAP with '%s'" % filter_name query = query.filter(sql_filter) # end handle pre-packaged filter # sort it query = query.order_by(getattr(SQLType.id, args.order == self.ORDER_DESC and 'desc' or 'asc')()) limit = args.limit is None and self.LIMIT_DEFAULT or args.limit if limit > 0: query = query.limit(limit) # end finally, set limit # Convert data to report ######################## record = report.records.append count = -1 for count, item in enumerate(query): record(tuple(getattr(item, vals[0]) for vals in schema)) # end for each item # And output it report.serialize(args.output_mode, sys.stdout.write, column_names=not args.no_header) if count == -1: sys.stderr.write("No '%s' record found\n" % args.type) if count + 1 == limit: sys.stderr.write("WARNING: Output was limited to %i - see the --limit flag\n" % args.limit) # end handle warnings and errors return self.SUCCESS
def _handle_transactions(self, args, session): """Implement transaction subcommand""" if args.action in self.query_actions: if args.reason: self.log().warn("--reason has no effect in query actions like %s", ', '.join(self.query_actions)) # end handle reason else: if not args.reason: self.log().error("Please specify a reason for performing the '%s' action, use the --reason argument", args.action) return self.ERROR # end need reason # end assure reason is set try: for tid in getattr(args, self.ARG_TRANSACTION_IDS): trans = session.query(SQLPackageTransaction).filter(SQLPackageTransaction.id == tid)[:] if not trans: raise ValueError("No transaction found with id %i" % tid) # end fail on missing transactions trans = trans[0] if args.action == self.ACTION_APPROVE: if trans.finished_at is not None or trans.started_at is not None: raise ValueError("Transaction %i is already done and cannot be approved after the fact" % tid) # end handle finished transactions trans.approved_by_login = login_name() self.log().info("Approved %i" % tid) elif args.action == self.ACTION_REJECT: trans.reject_approval() self.log().info("Rejected %i" % tid) elif args.action == self.ACTION_CANCEL: trans.cancel() self.log().info("Canceled %i" % tid) elif args.action == self.ACTION_LIST_FILES: print "Files for transaction %i" % tid report = Report(columns=self.report_schema_files) record = report.records.append for f in trans.files: try: uid = getpwuid(f.uid).pw_name except KeyError: uid = f.uid # end remap uid if possible record((f.path, f.size, uid, f.gid, f.mode)) # end for each file report.serialize(Report.SERIALIZE_TTY, sys.stdout.write) else: raise NotImplemented("unknown action: %s" % args.action) # end handle action # Always keep the reason around if args.action not in self.query_actions: assert args.reason trans.reason = args.reason # end assure reason is set only in edit mode # end for each tid session.commit() except Exception, err: self.log().error(str(err)) if args.action not in self.query_actions: session.rollback() self.log().error("Failed to set transaction - all progress rolled back") # end don't warn if we are read-only return self.ERROR
def execute(self, args, remaining_args): config = self.settings_value() session = ZSession.new() zcls = args.type == ZReportGenerator.TYPE_POOL and ZPool or ZDataset query = session.query(zcls) table = zcls.__table__ columns = table.columns.keys() hosts_attribute = zcls.host name_attribute = zcls.name columns_important = getattr(config.columns, args.type) if args.type == ZReportGenerator.TYPE_SNAPSHOT: query = query.filter(ZDataset.avail == None) columns_important = config.columns.snapshot elif args.type == ZReportGenerator.TYPE_FILESYSTEM: query = query.filter(ZDataset.avail != None).filter(ZDataset.type == ZReportGenerator.TYPE_FILESYSTEM) columns_important = config.columns.filesystem # COLUMNS FILTER ################# if args.columns: has_user_columns = True if len(args.columns) == 1 and args.columns[0] in (self.COLUMN_ALL, self.COLUMN_IMPORTANT): if args.columns[0] == self.COLUMN_IMPORTANT: args.columns = columns_important else: has_user_columns = False # end handle 'all' # end handle presets if has_user_columns: columns = self.verify_columns(table.columns, args.columns) if not columns: return self.ERROR # end early abort # end handle special case: all # end check provided columns # Always use the updated_at column columns.insert(0, 'updated_at') # HOSTS FILTER ############## if args.host: query = query.filter(hosts_attribute == args.host) # end # Name filter ############## if args.name: name = '%%%s%%' % args.name query = query.filter(name_attribute.like(name)) # end handle name filter # ORDER ######### # NOTE: if there is no order, order by creation ascending ! if not args.order_by_asc and not args.order_by_desc: args.order_by_asc = ['host', 'creation'] # end auto-order for attr, order in (('order_by_asc', 'asc'), ('order_by_desc', 'desc')): order_cols = getattr(args, attr) if not order_cols: continue # end handle order_cols order_cols = self.columns_by_names(table.columns, order_cols) if order_cols: query = query.order_by(*(getattr(col, order)() for col in order_cols)) # end for each attr, order rep = Report() rep.columns = self.table_schema_from_colums(table.columns, columns) now = datetime.now() # FILL RECORDS ############## col_to_attr = zcls.__mapper__.get_property_by_column name_to_col = table.columns.__getitem__ for inst in query: rec = list() if isinstance(inst, ZDataset) and args.leaf and not inst.is_snapshot() and list(inst.children()): continue # end skip non-leaf datasets for cid, name in enumerate(columns): if name == self.COLUMN_URL: val = str(ZFSURL.new_from_dataset(inst.host, inst.name)) else: val = getattr(inst, col_to_attr(name_to_col(name)).key) if isinstance(val, datetime): val = now - val # end handle conversions # end handle special case rec.append(val) # end for each colum rep.records.append(rec) # end for each row # AGGREGATION ################## if len(rep.records) > 1: agr = rep.aggregate_record() agr[0] = now - now rep.records.append(agr) if args.aggregate_only: rep.records = rep.records[-1:] # end remove all records but aggregate # end aggregate only if there is something # Finally, make sure updated_at becomes seen - we now have the values and no one cares about the schema # names anymore for col in rep.columns: if col[0] == 'updated_at': col[0] = 'seen' # end rename updated_at rep.serialize(Report.SERIALIZE_TTY, sys.stdout.write) return self.SUCCESS