@@ -83,21 +83,25 @@ class Instance():
8383 status = staticmethod (print_status )
8484
8585 # each instance has a lot of data against it, we need to store only a few as attributes
86- useful_keys = ["project_id " , "project_name" , "size_used" , "size" , "state" ]
86+ useful_keys = ["instance_id " , "project_name" , "size_used" , "size" , "state" ]
8787
8888 def __init__ (self , i : str , * , workspace_id : str = "" ):
8989 """NBX-Build Instance class manages the both individual instance, but provides webserver functionality using
9090 `nbox_ws_v1`, such as starting and stopping, deletion and more.
9191
9292 Args:
93- i (str): name or `project_id ` of the instance
93+ i (str): name or `instance_id ` of the instance
9494 """
9595 if not i :
9696 raise ValueError ("Instance id must be provided, try --i='1023'" )
97+
98+ # if user provided a number we assume that they gave an instance ID, this is a weak assumption because
99+ # people usually use names.
100+ _instance_id = isinstance (i , int )
97101 i = str (i )
98102
99103 # simply add useful keys to the instance
100- self .project_id : str = None
104+ self .instance_id : str = None
101105 self .project_name : str = None
102106 self .workspace_id : str = workspace_id or secret .workspace_id
103107 self .size_used : float = None
@@ -113,31 +117,36 @@ def __init__(self, i: str, *, workspace_id: str = ""):
113117 stub_ws_instance = create_webserver_subway ("v1" , sess )
114118 stub_projects = stub_ws_instance .instances
115119
116- # filter and get the data
117- project_details = stub_projects ()["project_details" ]
118- # print(project_details)
119- if i not in project_details :
120- by_name = list (filter (lambda x : x [1 ]['project_name' ] == i , list (project_details .items ())))
121- if len (by_name ) == 0 :
122- raise ValueError (f"Instance '{ i } ' not found" )
123- elif len (by_name ) > 1 :
124- raise ValueError (f"Multiple instances with name '{ i } ' found" )
125- data = by_name [0 ]
126- project_id = data [0 ]
127- data = data [1 ]
120+ if _instance_id :
121+ # if user provided an instance id, we can directly get the data
122+ data = stub_projects .u (i )()
123+ instance_id = i
128124 else :
129- data = project_details [i ]
130- project_id = i
131- data ["project_id" ] = project_id
132- logger .info (f"Found instance '{ data ['project_name' ]} ' ({ data ['project_id' ]} )" )
125+ # else filter and get the data
126+ project_details = stub_projects ()["project_details" ]
127+ if i not in project_details :
128+ by_name = list (filter (lambda x : x [1 ]['project_name' ] == i , list (project_details .items ())))
129+ if len (by_name ) == 0 :
130+ raise ValueError (f"Instance '{ i } ' not found" )
131+ elif len (by_name ) > 1 :
132+ raise ValueError (f"Multiple instances with name '{ i } ' found" )
133+ data = by_name [0 ]
134+ instance_id = data [0 ]
135+ data = data [1 ]
136+ else :
137+ data = project_details [i ]
138+ instance_id = i
139+
140+ data ["instance_id" ] = instance_id
141+ logger .info (f"Found instance '{ data ['project_name' ]} ' ({ data ['instance_id' ]} )" )
133142 # print(data)
134- for x in self .useful_keys :
143+ for x in Instance .useful_keys :
135144 setattr (self , x , data [x ])
136145
137146 # some data points require extra processing before usage
138147 self .custom_ports : Dict [str , int ] = loads (data ["custom_ports" ]) if data ["custom_ports" ] is not None else {}
139148 self .exposed_ports : Dict [str , int ] = loads (data ["exposed_ports" ]) if data ["exposed_ports" ] is not None else {}
140- self .stub_ws_instance = stub_projects .u (self .project_id )
149+ self .stub_ws_instance = stub_projects .u (self .instance_id )
141150 logger .debug (f"WS: { self .stub_ws_instance } " )
142151
143152 # set values
@@ -257,13 +266,13 @@ def is_running(self) -> bool:
257266
258267 def refresh (self ):
259268 """Update the data, get latest state"""
260- self .data = self .stub_ws_instance () # GET /user/projects/{project_id }
269+ self .data = self .stub_ws_instance () # GET /user/projects/{instance_id }
261270 for k in self .useful_keys :
262271 setattr (self , k , self .data [k ])
263272
264273 def _start (self , cpu , gpu , gpu_count , auto_shutdown , dedicated_hw , zone ):
265274 """Turn on the the unserlying compute"""
266- logger .info (f"Starting instance { self .project_name } ({ self .project_id } )" )
275+ logger .info (f"Starting instance { self .project_name } ({ self .instance_id } )" )
267276 hw_config = {
268277 "cpu" :f"n1-standard-{ cpu } "
269278 }
@@ -283,21 +292,21 @@ def _start(self, cpu, gpu, gpu_count, auto_shutdown, dedicated_hw, zone):
283292 region = zone
284293 )
285294
286- logger .info (f"Waiting for instance { self .project_name } ({ self .project_id } ) to start ..." )
295+ logger .info (f"Waiting for instance { self .project_name } ({ self .instance_id } ) to start ..." )
287296 _i = 0
288297 while self .state != "RUNNING" :
289298 time .sleep (5 )
290299 self .refresh ()
291300 _i += 1
292301 if _i > TIMEOUT_CALLS :
293302 raise TimeoutError ("Instance did not start within timeout, please check dashboard" )
294- logger .info (f"Instance { self .project_name } ({ self .project_id } ) started" )
303+ logger .info (f"Instance { self .project_name } ({ self .instance_id } ) started" )
295304
296305 def _open (self ):
297306 # now the instance is running, we can open it, opening will assign a bunch of cookies and
298307 # then get us the exact location of the instance
299308 if not self .__opened :
300- logger .debug (f"Opening instance { self .project_name } ({ self .project_id } )" )
309+ logger .debug (f"Opening instance { self .project_name } ({ self .instance_id } )" )
301310 launch_data = self .stub_ws_instance .launch (_method = "post" )
302311 base_domain = launch_data ['base_domain' ]
303312 self .open_data = {
@@ -340,7 +349,7 @@ def start(
340349 self ._start (cpu , gpu , gpu_count , auto_shutdown , dedicated_hw , zone )
341350 else :
342351 # TODO: @yashbonde: inform user in case of hardware mismatch?
343- logger .info (f"Instance { self .project_name } ({ self .project_id } ) is already running" )
352+ logger .info (f"Instance { self .project_name } ({ self .instance_id } ) is already running" )
344353
345354 # prevent rate limiting
346355 if not self .__opened :
@@ -349,31 +358,34 @@ def start(
349358 def stop (self ):
350359 """Stop the Instance"""
351360 if self .state == "STOPPED" :
352- logger .info (f"Instance { self .project_name } ({ self .project_id } ) is already stopped" )
361+ logger .info (f"Instance { self .project_name } ({ self .instance_id } ) is already stopped" )
353362 return
354363
355- logger .debug (f"Stopping instance { self .project_name } ({ self .project_id } )" )
356- message = self .stub_ws_instance .stop_instance ("post" , data = {"instance_id" :self .project_id })["msg" ]
364+ logger .debug (f"Stopping instance { self .project_name } ({ self .instance_id } )" )
365+ message = self .stub_ws_instance .stop (
366+ "post" ,
367+ data = {"workspace_id" : secret .workspace_id , "instance_id" : self .instance_id }
368+ )["msg" ]
357369 if not message == "success" :
358370 raise ValueError (message )
359371
360- logger .debug (f"Waiting for instance { self .project_name } ({ self .project_id } ) to stop" )
372+ logger .debug (f"Waiting for instance { self .project_name } ({ self .instance_id } ) to stop" )
361373 _i = 0 # timeout call counter
362374 while self .state != "STOPPED" :
363375 time .sleep (5 )
364376 self .refresh ()
365377 _i += 1
366378 if _i > TIMEOUT_CALLS :
367379 raise TimeoutError ("Instance did not stop within timeout, please check dashboard" )
368- logger .debug (f"Instance { self .project_name } ({ self .project_id } ) stopped" )
380+ logger .debug (f"Instance { self .project_name } ({ self .instance_id } ) stopped" )
369381
370382 self .__opened = False
371383
372384 def delete (self , force = False ):
373385 """With great power comes great responsibility."""
374386 if self .__opened and not force :
375387 raise ValueError ("Instance is still opened, please call .stop() first" )
376- logger .warning (f"Deleting instance { self .project_name } ({ self .project_id } )" )
388+ logger .warning (f"Deleting instance { self .project_name } ({ self .instance_id } )" )
377389 if input (f"> Are you sure you want to delete '{ self .project_name } '? (y/N): " ) == "y" :
378390 self .stub_ws_instance ("delete" )
379391 else :
@@ -390,8 +402,8 @@ def delete(self, force = False):
390402 def _unopened_error (self ):
391403 if not self .__opened :
392404 logger .error (f"You are trying to move files to a { self .state } instance, you will have to start the instance first:" )
393- logger .error (f' - nbox.Instance("{ self .project_id } ", "{ self .workspace_id } ").start(...)' )
394- logger .error (f' - python3 -m nbox build --i "{ self .project_id } " --workspace_id "{ self .workspace_id } " start --help' )
405+ logger .error (f' - nbox.Instance("{ self .instance_id } ", "{ self .workspace_id } ").start(...)' )
406+ logger .error (f' - python3 -m nbox build --i "{ self .instance_id } " --workspace_id "{ self .workspace_id } " start --help' )
395407 raise ValueError ("Instance is not opened, please call .open() first" )
396408
397409 def __create_connection (self , * , port : int = 6174 ):
@@ -401,7 +413,7 @@ def __create_connection(self, *, port: int = 6174):
401413 # create logging for RSock
402414 folder = U .join (U .env .NBOX_HOME_DIR (), "tunnel_logs" )
403415 os .makedirs (folder , exist_ok = True )
404- filepath = U .join (folder , f"tunnel_{ self .project_id } .log" ) # consistency with IDs instead of names
416+ filepath = U .join (folder , f"tunnel_{ self .instance_id } .log" ) # consistency with IDs instead of names
405417 file_logger = FileLogger (filepath )
406418 logger .debug (f"Logging RSock server to { filepath } " )
407419
0 commit comments