async def main(_loop): no_extend_label = "CANNOT_EXTEND" extend_label = "CAN_EXTEND" try: jira = Jira( Config["jira_url"], loop=_loop, ) except JiraException as ex: logger.error(ex) return 1 tickets = await jira.get_pending_tickets() for ticket in tickets["issues"]: ticket_key = ticket.get("key").split("-")[-1] fields = ticket.get("fields") if fields: description = fields.get("description") try: cloud_field = description.split("\n")[1] cloud = cloud_field.split()[-1] except IndexError: logger.warning( f"Could not retrieve cloud name from ticket {ticket_key}") cloud_obj = Cloud.objects(name=cloud).first() schedules = Schedule.current_schedule(cloud=cloud_obj) conflict = False for schedule in schedules: end_date = schedule.end + timedelta(weeks=2) available = Schedule.is_host_available(host=schedule.host.name, start=schedule.end, end=end_date) if not available: conflict = True await jira.add_label(ticket_key, no_extend_label) logger.info(f"{cloud} labeled {no_extend_label}") break if not conflict: await jira.add_label(ticket_key, extend_label) logger.info(f"{cloud} labeled {extend_label}") parent = fields.get("parent") if parent: p_ticket_key = parent.get("key").split("-")[-1] watchers = await jira.get_watchers(p_ticket_key) for watcher in watchers["watchers"]: await jira.add_watcher(ticket_key, watcher["key"]) return 0
def available(search): models = search.data['model'] if models: query = None for model in models: if query: query = query | Q(model=model.upper()) else: query = Q(model=model.upper()) hosts = Host.objects.filter(query) else: hosts = Host.objects().all() loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) foreman = Foreman( conf["foreman_api_url"], conf["foreman_username"], conf["foreman_password"], loop=loop, ) broken_hosts = loop.run_until_complete(foreman.get_broken_hosts()) available_hosts = [] start = datetime.combine(search.data['start'], time.min) end = datetime.combine(search.data['end'], time.min) if hosts: for host in hosts: if Schedule.is_host_available( host=host["name"], start=start, end=end) and not broken_hosts.get(host["name"], False): host_dict = {"name": host.name, "model": host.model} available_hosts.append(host_dict) return jsonify(available_hosts)
def available(search): models = search.data["model"] if models: query = None for model in models: if query: query = query | Q(model=model.upper()) else: query = Q(model=model.upper()) hosts = Host.objects.filter(query) else: hosts = Host.objects().all() available_hosts = [] start = datetime.combine(search.data["start"], time(hour=22)) end = datetime.combine(search.data["end"], time(hour=22)) if hosts: for host in hosts: if Schedule.is_host_available(host=host["name"], start=start, end=end): current = False if Schedule.current_schedule(host=host): current = True host_dict = { "name": host.name, "cloud": host.cloud.name, "model": host.model, "current": current } available_hosts.append(host_dict) return jsonify(available_hosts)
def GET(self, **data): args = {} _cloud = None _host = None if "cloudonly" in data: _cloud = Cloud.objects(cloud=data["cloudonly"]) if not _cloud: cherrypy.response.status = "404 Not Found" return json.dumps( {"result": "Cloud %s Not Found" % data["cloudonly"]}) else: return _cloud.to_json() if self.name == "host": if "id" in data: _host = Host.objects(id=data["id"]).first() elif "name" in data: _host = Host.objects(name=data["name"]).first() elif "cloud" in data: _cloud = Cloud.objects(name=data["cloud"]).first() _host = Host.objects(cloud=_cloud) else: _host = Host.objects() if not _host: return json.dumps({"result": ["Nothing to do."]}) return _host.to_json() if self.name == "ccuser": _clouds = self.model.objects().all() clouds_summary = [] for cloud in _clouds: count = Schedule.current_schedule(cloud=cloud).count() clouds_summary.append({ "name": cloud.name, "count": count, "description": cloud.description, "owner": cloud.owner, "ticket": cloud.ticket, "ccuser": cloud.ccuser, "provisioned": cloud.provisioned, }) return json.dumps(clouds_summary) if self.name == "cloud": if "id" in data: _cloud = Cloud.objects(id=data["id"]).first() elif "name" in data: _cloud = Cloud.objects(name=data["name"]).first() elif "owner" in data: _cloud = Cloud.to_json(owner=data["owner"]).first() if _cloud: return _cloud.to_json() if self.name == "available": _start = _end = datetime.datetime.now() if "start" in data: _start = datetime.datetime.strptime(data["start"], "%Y-%m-%dT%H:%M:%S") if "end" in data: _end = datetime.datetime.strptime(data["end"], "%Y-%m-%dT%H:%M:%S") available = [] all_hosts = Host.objects().all() for host in all_hosts: if Schedule.is_host_available(host=host["name"], start=_start, end=_end): available.append(host.name) return json.dumps(available) if self.name == "summary": _clouds = Cloud.objects().all() clouds_summary = [] total_count = 0 for cloud in _clouds: if cloud.name == "cloud01": count = Host.objects(cloud=cloud, retired=False, broken=False).count() else: date = datetime.datetime.now() if "date" in data: date = datetime.datetime.strptime( data["date"], "%Y-%m-%dT%H:%M:%S") count = self.model.current_schedule(cloud=cloud, date=date).count() total_count += count clouds_summary.append({ "name": cloud.name, "count": count, "description": cloud.description, "owner": cloud.owner, "ticket": cloud.ticket, "ccuser": cloud.ccuser, "provisioned": cloud.provisioned, "validated": cloud.validated, }) if "date" in data: host_count = Host.objects(retired=False, broken=False).count() for cloud in clouds_summary: if cloud["name"] == "cloud01": cloud["count"] = host_count - total_count return json.dumps(clouds_summary) if self.name == "qinq": _clouds = Cloud.objects().all() clouds_qinq = [] for cloud in _clouds: _type = "Isolated" if cloud.qinq == 1: _type = "Combined" qinq_value = f"{cloud.qinq} ({_type})" clouds_qinq.append({"name": cloud.name, "qinq": qinq_value}) return json.dumps(clouds_qinq) if self.name == "broken": _hosts = self.model.objects(broken=True) broken = [] for host in _hosts: broken.append(host.name) return json.dumps(broken) if self.name == "retired": hosts = [host.name for host in self.model.objects(retired=True)] return json.dumps(hosts) objs = self.model.objects(**args) if objs: return objs.to_json() else: return json.dumps({"result": ["No results."]})
def POST(self, **data): # make sure post data passed in is ready to pass to mongo engine result, data = Schedule.prep_data(data) _start = None _end = None if "start" in data: _start = datetime.datetime.strptime(data["start"], "%Y-%m-%d %H:%M") if "end" in data: _end = datetime.datetime.strptime(data["end"], "%Y-%m-%d %H:%M") _host = data["host"] _host_obj = Host.objects(name=_host).first() broken_hosts = Host.objects(broken=True) if _host_obj in broken_hosts: result.append(f"Host {_host_obj.name} is in broken state") # Check if there were data validation errors if result: result = ["Data validation failed: %s" % ", ".join(result)] cherrypy.response.status = "400 Bad Request" return json.dumps({"result": result}) cloud_obj = None if "cloud" in data: cloud_obj = Cloud.objects(name=data["cloud"]).first() if not cloud_obj: result.append("Provided cloud does not exist") cherrypy.response.status = "400 Bad Request" return json.dumps({"result": result}) if "index" in data: data["host"] = _host_obj schedule = self.model.objects(index=data["index"], host=data["host"]).first() if schedule: if not _start: _start = schedule.start if not _end: _end = schedule.end if not cloud_obj: cloud_obj = schedule.cloud if Schedule.is_host_available(host=_host, start=_start, end=_end, exclude=schedule.index): data["cloud"] = cloud_obj notification_obj = Notification.objects( cloud=cloud_obj, ticket=cloud_obj.ticket).first() if notification_obj: notification_obj.update( one_day=False, three_days=False, five_days=False, seven_days=False, ) schedule.update(**data) result.append("Updated %s %s" % (self.name, schedule.index)) else: result.append( "Host is not available during that time frame") else: try: if Schedule.is_host_available(host=_host, start=_start, end=_end): if (self.model.current_schedule(cloud=cloud_obj) and cloud_obj.validated): if not cloud_obj.wipe: _host_obj.update(validated=True) notification_obj = Notification.objects( cloud=cloud_obj, ticket=cloud_obj.ticket).first() if notification_obj: notification_obj.update(success=False) schedule = Schedule() data["cloud"] = cloud_obj schedule.insert_schedule(**data) cherrypy.response.status = "201 Resource Created" result.append("Added schedule for %s on %s" % (data["host"], cloud_obj.name)) else: result.append( "Host is not available during that time frame") except Exception as e: # TODO: make sure when this is thrown the output # points back to here and gives the end user # enough information to fix the issue cherrypy.response.status = "500 Internal Server Error" result.append("Error: %s" % e) return json.dumps({"result": result})
def report_available(_logger, _start, _end): start = _start.replace(hour=22, minute=0, second=0) end = _end.replace(hour=22, minute=0, second=0) next_sunday = start + timedelta(days=(6 - start.weekday())) hosts = Host.objects() _logger.info(f"QUADS report for {start.date()} to {end.date()}:") days = 0 total_allocated_month = 0 total_hosts = len(hosts) for _date in date_span(start, end): total_allocated_month += Schedule.current_schedule(date=_date).count() days += 1 utilized = total_allocated_month * 100 // (total_hosts * days) _logger.info(f"Percentage Utilized: {utilized}%") schedules = Schedule.objects(build_start__ne=None, build_end__ne=None) total = timedelta() for schedule in schedules: total += schedule.build_end - schedule.build_start if schedules: average_build = total / len(schedules) _logger.info(f"Average build delta: {average_build}") hosts_summary = {} for host in hosts: host_type = host.name.split(".")[0].split("-")[-1] if not hosts_summary.get(host_type): hosts_summary[host_type] = [] hosts_summary[host_type].append(host) headers = [ "Server Type", "Total", "Free", "Scheduled", "2 weeks", "4 weeks" ] _logger.info(f"{headers[0]:<12}| " f"{headers[1]:>5}| " f"{headers[2]:>5}| " f"{headers[3]:>9}| " f"{headers[4]:>7}| " f"{headers[5]:>7}") for host_type, _hosts in hosts_summary.items(): scheduled_count = 0 two_weeks_availability_count = 0 four_weeks_availability_count = 0 for host in _hosts: schedule = Schedule.current_schedule(host=host) if schedule: scheduled_count += 1 two_weeks_availability = Schedule.is_host_available( host=host.name, start=next_sunday, end=next_sunday + timedelta(weeks=2)) if two_weeks_availability: two_weeks_availability_count += 1 four_weeks_availability = Schedule.is_host_available( host=host.name, start=next_sunday, end=next_sunday + timedelta(weeks=4)) if four_weeks_availability: four_weeks_availability_count += 1 free = len(_hosts) - scheduled_count schedule_percent = scheduled_count * 100 // len(_hosts) _logger.info(f"{host_type:<12}| " f"{len(_hosts):>5}| " f"{free:>5}| " f"{schedule_percent:>8}%| " f"{two_weeks_availability_count:>7}| " f"{four_weeks_availability_count:>7}")