cloudFPGA (cF) API  1.0
The documentation of the source code of cloudFPGA (cF)
cfsp_cluster.py
Go to the documentation of this file.
1 # *****************************************************************************
2 # * cloudFPGA
3 # * Copyright 2016 -- 2022 IBM Corporation
4 # * Licensed under the Apache License, Version 2.0 (the "License");
5 # * you may not use this file except in compliance with the License.
6 # * You may obtain a copy of the License at
7 # *
8 # * http://www.apache.org/licenses/LICENSE-2.0
9 # *
10 # * Unless required by applicable law or agreed to in writing, software
11 # * distributed under the License is distributed on an "AS IS" BASIS,
12 # * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # * See the License for the specific language governing permissions and
14 # * limitations under the License.
15 # *----------------------------------------------------------------------------
16 
17 """
18 Usage:
19  cfsp cluster (get | post | extend | update | restart | delete)
20 Commands:
21  get <id> Get all clusters of a user. Either <id> of cluster or no argument for all.
22  post Request a cluster.
23  extend id Add nodes to an existing cluster
24  update id Reconfigure one FPGA node of an existing cluster
25  restart id Restart all applications on FPGAs in this cluster
26  delete id Delete a cluster with cluster_id=id. If no id is provided then all clusters are deleted (after confirmation dialog with user)
27 """
28 from __future__ import absolute_import
29 
30 import sys,os
31 #python_api_client_path = os.getcwd()+"/cFSPlib/python_api_client/"
32 python_api_client_path = os.path.dirname(os.path.abspath(__file__))+"/python_api_client/"
33 
34 sys.path.append(python_api_client_path)
35 
36 import cfsp_globals
37 import swagger_client
38 from swagger_client.api.clusters_api import ClustersApi # noqa: E501
39 from swagger_client.rest import ApiException
40 from swagger_client.api_client import ApiClient
41 from swagger_client.configuration import Configuration
42 from tqdm import tqdm
43 
45  confirm = input("[c]Confirm or [v]Void: ")
46  if confirm != 'c' and confirm != 'v':
47  print("\n Invalid Option. Please Enter a Valid Option.")
48  return confirm_choice()
49  print (confirm)
50  return confirm
51 
52 
53 def main(args):
54  conf = Configuration()
55  conf.host = cfsp_globals.__cf_manager_url__
56  api_client = ApiClient(conf)
57  api_instance = ClustersApi(api_client=api_client)
58 
59  if ((len(args['<args>']) < 1) or (len(args['<args>']) > 2)):
60  print("ERROR: invalid arguments provided in 'cfsp cluster' command. Aborting...")
61  exit(print(__doc__))
62 
63  username = cfsp_globals.__cfsp_username__
64  password = cfsp_globals.__cfsp_password__
65  project_name = cfsp_globals.__cfsp_project__
66 
67  if args['<args>'][0] == 'get':
68  if (len(args['<args>']) == 2):
69  try:
70  api_response = api_instance.cf_manager_rest_api_get_cluster_single(username, password, args['<args>'][1])
71  except ApiException as e:
72  print("Exception when calling ClustersApi->cf_manager_rest_api_get_cluster_single: %s\n" % e)
73  exit(-1)
74  elif (len(args['<args>']) == 1):
75  try:
76  api_response = api_instance.cf_manager_rest_api_get_clusters(username, password, limit=args['--limit'])
77  except ApiException as e:
78  print("Exception when calling ClustersApi->cf_manager_rest_api_get_clusters: %s\n" % e)
79  exit(-1)
80  else:
81  exit(print("ERROR: invalid arguments provided in cfsp cluster get. Aborting..."))
82  return(api_response)
83  elif (args['<args>'][0] == 'post') or (args['<args>'][0] == 'extend'):
84  # create an instance of the API class
85  body = []
86  cpu_num = len(args['--node_ip'])
87  fpga_num = len(args['--image_id'])
88  node_id_num = len(args['--node_id'])
89 
90  if node_id_num == 0:
91  print("WARNING: No --node_id argument was provided. Incremental ids will be used for fpga(s) and cpu(s) in this cluster.")
92  for i in range(fpga_num):
93  args['--node_id'].append(i)
94  for j in range(cpu_num):
95  args['--node_id'].append(fpga_num+j)
96  else:
97  if (node_id_num != cpu_num + fpga_num):
98  exit(print("ERROR: The provided argument(s) of --node_id ("+str(node_id_num)+") is not the same with the sum of --node_ip ("+str(cpu_num)+") and --image_id ("+str(fpga_num)+") ones. Please note that for each of --node_ip and --image_id, a --node_id argument is required. Aborting..."))
99 
100  # Convert the node_id list to ints
101  args['--node_id'] = list(map(int, args['--node_id']))
102 
103  print("INFO: Please review the assignment of image_id(s), node_ip(s) and node_id(s)")
104  print("[image_id, node_id]")
105  for i in range(fpga_num):
106  fpga_body = { "image_id": args['--image_id'][i], "node_id": args['--node_id'][i] }
107  print("["+args['--image_id'][i] + ", " + str(args['--node_id'][i]) + "]")
108  body.append(fpga_body)
109  print("[node_ip, node_id]")
110  for j in range(cpu_num):
111  cpu_body = { "image_id": cfsp_globals.__NON_FPGA_IDENTIFIER__, "node_ip": args['--node_ip'][j], "node_id": args['--node_id'][fpga_num+j] }
112  print("["+args['--node_ip'][j] + ", " + str(args['--node_id'][fpga_num+j]) + "]")
113  body.append(cpu_body)
114 
115  if (args['<args>'][0] == 'post'):
116  try:
117  # Request a cluster
118  api_response = api_instance.cf_manager_rest_api_post_clusters(body, username, password, project_name=project_name, dont_verify_memory=args['--dont_verify_memory'])
119  return(api_response)
120  except ApiException as e:
121  print("Exception when calling ClustersApi->cf_manager_rest_api_post_clusters: %s\n" % e)
122  exit(-1)
123  elif args['<args>'][0] == 'extend':
124  try:
125  # Request to extend cluster
126  api_response = api_instance.cf_manager_rest_api_extend_cluster(body, username, password, cluster_id=args['--cluster_id'], dont_verify_memory=args['--dont_verify_memory'])
127  return(api_response)
128  except ApiException as e:
129  print("Exception when calling ClustersApi->cf_manager_rest_api_extend_cluster: %s\n" % e)
130  exit(-1)
131  elif (args['<args>'][0] == 'reduce'):
132  node_id_num = len(args['--node_id'])
133  body = []
134 
135  # Convert the node_id list to ints
136  args['--node_id'] = list(map(int, args['--node_id']))
137 
138  for i in range(node_id_num):
139  node_id_body = args['--node_id'][i]
140  body.append(node_id_body)
141  try:
142  # Request to extend cluster
143  api_response = api_instance.cf_manager_rest_api_reduce_cluster(body, username, password, cluster_id=args['--cluster_id'])
144  return(api_response)
145  except ApiException as e:
146  print("Exception when calling ClustersApi->cf_manager_rest_api_reduce_cluster: %s\n" % e)
147  exit(-1)
148  elif (args['<args>'][0] == 'update'):
149  node_id_num = len(args['--node_id'])
150  cpu_num = len(args['--node_ip'])
151  fpga_num = len(args['--image_id'])
152  try:
153  cluster_id_num = len(args['--cluster_id'])
154  except:
155  exit(print("ERROR: The argument --cluster_id must be provided once. Aborting..."))
156 
157  if (cpu_num != 0):
158  # Update CPU
159  if (fpga_num != 0):
160  exit(print("ERROR: The argument --image_id cannot be provided together with --node_ip in cluster update (i.e. cannot simultanously update CPU and FPGA nodes). Aborting..."))
161 
162  if (node_id_num == 0):
163  print("WARNING: No argument --node_id was provided. Will try to locate CPU node_id's in cluster "+ str(args['--cluster_id'])+ " ...")
164  try:
165  api_response = api_instance.cf_manager_rest_api_get_cluster_single(username, password, args['--cluster_id'])
166  except ApiException as e:
167  print("Exception when calling ClustersApi->cf_manager_rest_api_get_cluster_single: %s\n" % e)
168  exit(-1)
169 
170  nodes_in_cluster_len = len(api_response.nodes)
171  for i in range(nodes_in_cluster_len):
172  #if (api_response.nodes[i].['image_id'] != 'NON_FPGA'):
173  if (api_response.nodes[i].get('image_id') == 'NON_FPGA'):
174  print("INFO: Found CPU node at id : " + str(api_response.nodes[i].get('node_id')) + ", with ip : " + str(api_response.nodes[i].get('node_ip')))
175  args['--node_id'].append(api_response.nodes[i].get('node_id'))
176  else:
177  # Convert the node_id list to ints
178  args['--node_id'] = list(map(int, args['--node_id']))
179 
180  node_id_num = len(args['--node_id'])
181  if (node_id_num != cpu_num):
182  exit(print("ERROR: The list of CPU nodes provided or found on the cluster " + str(args['--cluster_id']) + " ("+ str(node_id_num) + ") is not equal to the number of new IPs for CPUs provided (" + str(cpu_num) + ") in cluster update. Aborting..."))
183 
184  print("Reducing cluster...")
185  try:
186  # Request to update the CPU node of the cluster by removing the CPU node and adding a new one with the new ip
187  api_response = api_instance.cf_manager_rest_api_reduce_cluster(args['--node_id'], username, password, cluster_id=args['--cluster_id'])
188  except ApiException as e:
189  print("Exception when calling ClustersApi->cf_manager_rest_api_reduce_cluster: %s\n" % e)
190  exit(-1)
191 
192  #FIXME: add extend cluster with the new cpu
193  body = []
194  for j in range(cpu_num):
195  cpu_body = { "image_id": cfsp_globals.__NON_FPGA_IDENTIFIER__, "node_ip": args['--node_ip'][j], "node_id": args['--node_id'][j] }
196  print("["+args['--node_ip'][j] + ", " + str(args['--node_id'][j]) + "]")
197  body.append(cpu_body)
198 
199  print("Extending cluster...")
200  try:
201  # Request to extend cluster
202  api_response = api_instance.cf_manager_rest_api_extend_cluster(body, username, password, cluster_id=args['--cluster_id'], dont_verify_memory=args['--dont_verify_memory'])
203  return(api_response)
204  except ApiException as e:
205  print("Exception when calling ClustersApi->cf_manager_rest_api_extend_cluster: %s\n" % e)
206  exit(-1)
207 
208 
209  # We just return the last responce since it returns the whole cluster
210  return(api_response)
211 
212 
213  elif (fpga_num != 0):
214  # Update FPGA
215  if (fpga_num != 1):
216  exit(print("ERROR: The argument --image_id must be provided once. Aborting..."))
217  if (cpu_num != 0):
218  exit(print("ERROR: The argument --node_ip cannot be provided together with ----image_id in cluster update (i.e. cannot simultanously update FPGA and CPU nodes). Aborting..."))
219  if (node_id_num == 0):
220  print("WARNING: No argument --node_id was provided. Will try to locate FPGA node_id's in cluster "+ str(args['--cluster_id'])+ " ...")
221  try:
222  api_response = api_instance.cf_manager_rest_api_get_cluster_single(username, password, args['--cluster_id'])
223  except ApiException as e:
224  print("Exception when calling ClustersApi->cf_manager_rest_api_get_cluster_single: %s\n" % e)
225  exit(-1)
226 
227  nodes_in_cluster_len = len(api_response.nodes)
228  for i in range(nodes_in_cluster_len):
229  #if (api_response.nodes[i].['image_id'] != 'NON_FPGA'):
230  if (api_response.nodes[i].get('image_id') != 'NON_FPGA'):
231  print("INFO: Found FPGA node at id : " + str(api_response.nodes[i].get('node_id')) + ", with ip : " + str(api_response.nodes[i].get('node_ip')))
232  args['--node_id'].append(api_response.nodes[i].get('node_id'))
233  else:
234  # Convert the node_id list to ints
235  args['--node_id'] = list(map(int, args['--node_id']))
236 
237  node_id_num = len(args['--node_id'])
238 
239  for i in range(node_id_num):
240  try:
241  # Request to update cluster
242  api_response = api_instance.cf_manager_rest_api_update_node_of_cluster(args['--image_id'][0], username, password, cluster_id=args['--cluster_id'], node_id=args['--node_id'][i], dont_verify_memory=args['--dont_verify_memory'])
243  except ApiException as e:
244  print("Exception when calling ClustersApi->cf_manager_rest_api_update_node_of_cluster: %s\n" % e)
245  exit(-1)
246  # We just return the last responce since it returns the whole cluster
247  return(api_response)
248  else:
249  exit(print("ERROR: No arguments --image_id or --node_id is provided. Aborting..."))
250  elif args['<args>'][0] == 'restart':
251  if (len(args['<args>']) == 1):
252  cluster_id = args['--cluster_id']
253  elif (len(args['<args>']) == 2):
254  cluster_id = args['<args>'][1]
255  else:
256  exit(print("ERROR: invalid arguments provided in cfsp cluster restart. Aborting..."))
257  # Restart a cluster
258  print("INFO: Restarting cluster " + str(cluster_id) + " ... ")
259  try:
260  api_response = api_instance.cf_manager_rest_api_restart_cluster(username, password, cluster_id)
261  return(api_response)
262  except ApiException as e:
263  print("Exception when calling ClustersApi->cf_manager_rest_api_restart_cluster: %s\n" % e)
264  exit(-1)
265  elif args['<args>'][0] == 'delete':
266  if (len(args['<args>']) == 1):
267  print("INFO: Trying deleting all clusters.")
268  try:
269  api_response_get_in_delete = api_instance.cf_manager_rest_api_get_clusters(username, password)
270  if(len(api_response_get_in_delete) > 0):
271  if(len(api_response_get_in_delete) == 1):
272  print("INFO: Really deleting cluster " + str(api_response_get_in_delete[0].cluster_id) + " ?")
273  else:
274  print("INFO: Really deleting all " + str(len(api_response_get_in_delete)) + " clusters ?")
275  if confirm_choice() == 'c':
276  print("INFO: Confirmed deleting all clusters.")
277  for this_cluster in tqdm(api_response_get_in_delete):
278  # Delete a cluster
279  print("INFO: Deleting cluster " + str(this_cluster.cluster_id) + " ... ")
280  try:
281  api_instance.cf_manager_rest_api_delete_cluster(username, password, this_cluster.cluster_id)
282  except ApiException as e_in_delete:
283  print("Exception when calling ClustersApi->cf_manager_rest_api_delete_cluster: %s\n" % e_in_delete)
284  else:
285  print ("INFO: Canceling deleting clsuter(s).")
286  else:
287  print("INFO: No clusters to delete.")
288  except ApiException as e_in_get:
289  print("Exception when calling ClustersApi->cf_manager_rest_api_get_clusters: %s\n" % e_in_get)
290  exit(-1)
291  elif (len(args['<args>']) == 2):
292  cluster_id = args['<args>'][1]
293  # Delete a cluster
294  print("INFO: Deleting cluster " + str(cluster_id) + " ... ")
295  try:
296  api_response = api_instance.cf_manager_rest_api_delete_cluster(username, password, cluster_id)
297  return(api_response)
298  except ApiException as e:
299  print("Exception when calling ClustersApi->cf_manager_rest_api_delete_cluster: %s\n" % e)
300  exit(-1)
301  else:
302  exit(print("ERROR: invalid arguments provided in cfsp cluster delete. Aborting..."))
303  else:
304  exit(print("ERROR: invalid command provided in cfsp cluster. Type 'cfsp help cluster' to get a list of supported commands. Aborting..."))
305 
306 if __name__ == '__main__':
307  main(args)
string input
Definition: test.py:9