Spaces:
Running
Running
File size: 8,283 Bytes
bfa4d7e 7a5c6c2 893770e 15120f2 7a5c6c2 893770e 5414557 e621e7d 1bb97ca e621e7d 2bbdb67 bfa4d7e 1bb97ca bfa4d7e 7a5c6c2 bfa4d7e 893770e bfa4d7e 893770e 7a5c6c2 e621e7d 7a5c6c2 bfa4d7e 7a5c6c2 893770e 15120f2 893770e 15120f2 893770e bfa4d7e 893770e 7a5c6c2 11b19c0 8048413 7a5c6c2 8048413 7a5c6c2 8048413 893770e 8048413 1505a4a 7a5c6c2 15120f2 8048413 893770e 15120f2 1505a4a 7a5c6c2 893770e 7a5c6c2 e621e7d 893770e 11b19c0 b49b34a bfa4d7e 893770e 2bbdb67 893770e 2bbdb67 893770e e621e7d 893770e 7a5c6c2 893770e 7a5c6c2 893770e 4a90c95 893770e bfa4d7e 016615c bfa4d7e 893770e 15120f2 bfa4d7e 2bbdb67 5414557 2bbdb67 bfa4d7e 15120f2 5414557 15120f2 d52e04f 5414557 15120f2 fbb7e2a d52e04f 15120f2 fbb7e2a 0021ec1 fbb7e2a 065cc17 2c51539 15120f2 e621e7d 339df26 e621e7d 893770e 15120f2 bfa4d7e 893770e 7a5c6c2 b49b34a 15120f2 7a5c6c2 8d74528 bfa4d7e 4a90c95 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | import os
import time
import requests
import gradio as gr
import openstack
from openstack import exceptions
# GLOBAL SHARED STATE
active_user_count = 0
is_comfit_alive = False
clean_link = "comfit-copilot.mch250095.projects.jetstream-cloud.org:3000"
full_url = f"http://{clean_link}"
# Styled HTML for a flashing neon green block with black text
GREEN_FLASHING_LINK = f"""
<style>
@keyframes flash {{
0% {{ opacity: 1; }}
50% {{ opacity: 0.4; }}
100% {{ opacity: 1; }}
}}
.flashing-btn {{
display: inline-block;
padding: 20px 40px;
font-size: 26px;
font-weight: 900;
text-decoration: none;
color: black !important;
background-color: #39FF14;
border: 5px solid black;
border-radius: 4px;
text-align: center;
animation: flash 1s infinite;
box-shadow: 0 0 20px #39FF14;
transition: transform 0.2s;
}}
.flashing-btn:hover {{
animation: none;
transform: scale(1.05);
opacity: 1;
}}
</style>
<div style="text-align: center; margin: 30px 0;">
<a href="{full_url}" target="_blank" class="flashing-btn">
CLICK HERE FOR COMFIT COPILOT
</a>
</div>
"""
def get_conn():
"""Authenticates with Jetstream2 (OpenStack) using Application Credentials."""
return openstack.connect(
auth_url=os.getenv("OS_AUTH_URL"),
application_credential_id=os.getenv("OS_APPLICATION_CREDENTIAL_ID"),
application_credential_secret=os.getenv("OS_APPLICATION_CREDENTIAL_SECRET"),
auth_type="v3applicationcredential",
region_name="IU",
interface="public"
)
def get_current_status():
global active_user_count, is_comfit_alive
try:
conn = get_conn()
instance_id = os.getenv("OS_INSTANCE_ID")
server = conn.compute.find_server(instance_id)
status_text = "β Error: Instance Not Found"
if server:
status_map = {
"ACTIVE": "π’ RUNNING (ACTIVE)",
"SHELVED_OFFLOADED": "π€ SLEEPING (SHELVED)",
"SHUTOFF": "π΄ POWERED OFF",
"BUILD": "π οΈ STARTING...",
"SHELVING": "β³ SAVING STATE..."
}
status_text = status_map.get(server.status, f"β STATE: {server.status}")
if "RUNNING" in status_text:
try:
if requests.get(full_url, timeout=2).status_code < 500:
is_comfit_alive = True
else:
is_comfit_alive = False
except:
is_comfit_alive = False
else:
is_comfit_alive = False
link_update = gr.update(value=GREEN_FLASHING_LINK if is_comfit_alive else "", visible=is_comfit_alive)
return status_text, f"π₯ Active Users: {active_user_count}", link_update
except Exception as e:
return f"β Error: {str(e)}", f"π₯ Active Users: {active_user_count}", gr.update()
def user_joined():
global active_user_count
active_user_count += 1
return f"π₯ Active Users: {active_user_count}"
def user_left():
global active_user_count
active_user_count = max(0, active_user_count - 1)
def manage_instance():
global is_comfit_alive
try:
conn = get_conn()
instance_id = os.getenv("OS_INSTANCE_ID")
server = conn.compute.find_server(instance_id)
if not server:
yield ("β Error: Instance Not Found", gr.update(visible=False))
return
if server.status != "ACTIVE":
yield ("β³ Milestone 1/3: Un-shelving Begin...", gr.update(visible=False))
if server.status == "SHELVED_OFFLOADED":
conn.compute.unshelve_server(server)
conn.compute.wait_for_server(server, status='ACTIVE', wait=600)
yield ("β
Milestone 2/3: Unshelved! VM is now ACTIVE.", gr.update(visible=False))
yield ("π Milestone 3/3: Connecting to ComFit...", gr.update(visible=False))
for i in range(24):
try:
if requests.get(full_url, timeout=3).status_code < 500:
is_comfit_alive = True
yield ("π Success! ComFit is ready.", gr.update(value=GREEN_FLASHING_LINK, visible=True))
return
except: pass
yield (f"π Milestone 3/3: Software booting ({i+1}/24)...", gr.update(visible=False))
time.sleep(5)
except Exception as e:
yield (f"β Error: {str(e)}", gr.update(visible=False))
combined_js = """
<script>
let idleTime = 0;
const MAX_IDLE = 10;
function playNotification(status) {
if (status.includes("RUNNING")) {
var audio = new Audio('https://cdn.freesound.org');
audio.play().catch(e => console.log("Audio play blocked."));
}
}
function resetTimer() { idleTime = 0; }
window.onmousemove = resetTimer; window.onmousedown = resetTimer; window.onclick = resetTimer; window.onkeypress = resetTimer;
setInterval(function() {
idleTime++;
if (idleTime >= MAX_IDLE) {
alert("Session Expired due to inactivity. Please refresh.");
window.location.reload();
}
}, 60000);
</script>
"""
# FIX 1: Removed theme=gr.themes.Soft() from here
with gr.Blocks() as demo:
gr.HTML(combined_js)
session_tracker = gr.State(value="active", delete_callback=user_left)
gr.Markdown("# ComFit Copilot (Comfort & Fit Copilot) By Innovision")
with gr.Row():
live_status = gr.Textbox(label="Live Jetstream2 Status (5s refresh)", interactive=False)
user_display = gr.Textbox(label="Space Activity", interactive=False)
with gr.Row():
activate_btn = gr.Button("π Activate / Access ComFit Copilot", variant="primary")
refresh_btn = gr.Button("π Force Refresh Status", variant="secondary")
status_label = gr.Label(value="Ready")
# Flashing link box
link_box = gr.HTML(visible=False)
gr.Markdown("---")
# CENTER ALIGNED INSTRUCTIONS HEADER
gr.Markdown("<center><h3>π Instructions for Visitors</h3></center>")
gr.Markdown("""
**Access or Wake Up**
- If a flashing **Green Button** is already visible (above these instructions), simply click it to open ComFit Copilot.
- If no flashing green button is visible, click **Activate / Access ComFit Copilot** button (top left). This will trigger the un-shelving process, which may take up to 2+ mins.
**Note A: Track Milestones**
The control panel will cycle through three milestones: Un-shelving, VM Activation, and Software Booting. Please wait while the cloud prepares your environment.
**Note B: Automatic Session Timeout**
If you do not interact with this page(or next page - ComFit Copilot interface) for **10 minutes**, your session will expire.
**Note C: What to do after clicking on flashing green button**
Once you sign-up using your email on ComFit Copilot page (next page), a button will pop-up showing that you need to confirm email. You can safely ignore this step(no need to open your inbox) and continue with login using information you just used for sign-up. Gmail/Microsoft 3rd party sign-up may not work for some users.
""")
# Logo Footer Section
gr.Markdown("---")
gr.Markdown("<center><h3>Thanks to our supporters & collaborators:</h3></center>")
with gr.Row():
gr.Image("logo1.png", show_label=False, interactive=False, container=False, scale=1)
gr.Image("logo2.png", show_label=False, interactive=False, container=False, scale=1)
gr.Image("logo3.png", show_label=False, interactive=False, container=False, scale=1)
live_status.change(None, inputs=live_status, js="(s) => playNotification(s)")
activate_btn.click(fn=manage_instance, outputs=[status_label, link_box])
refresh_btn.click(fn=get_current_status, outputs=[live_status, user_display, link_box])
timer = gr.Timer(5)
timer.tick(fn=get_current_status, outputs=[live_status, user_display, link_box])
demo.load(fn=user_joined, outputs=user_display)
demo.load(fn=get_current_status, outputs=[live_status, user_display, link_box])
if __name__ == "__main__":
# FIX 2: Added theme=gr.themes.Soft() here inside launch()
demo.launch(theme=gr.themes.Soft())
|