Package haizea :: Package cli :: Module rpc_commands
[hide private]
[frames] | no frames]

Source Code for Module haizea.cli.rpc_commands

  1  # -------------------------------------------------------------------------- # 
  2  # Copyright 2006-2009, University of Chicago                                 # 
  3  # Copyright 2008-2009, Distributed Systems Architecture Group, Universidad   # 
  4  # Complutense de Madrid (dsa-research.org)                                   # 
  5  #                                                                            # 
  6  # Licensed under the Apache License, Version 2.0 (the "License"); you may    # 
  7  # not use this file except in compliance with the License. You may obtain    # 
  8  # a copy of the License at                                                   # 
  9  #                                                                            # 
 10  # http://www.apache.org/licenses/LICENSE-2.0                                 # 
 11  #                                                                            # 
 12  # Unless required by applicable law or agreed to in writing, software        # 
 13  # distributed under the License is distributed on an "AS IS" BASIS,          # 
 14  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   # 
 15  # See the License for the specific language governing permissions and        # 
 16  # limitations under the License.                                             # 
 17  # -------------------------------------------------------------------------- # 
 18  import haizea.common.defaults as defaults 
 19  import haizea.common.constants as constants 
 20  from haizea.core.leases import Lease, Capacity, Duration, Timestamp, DiskImageSoftwareEnvironment 
 21  from haizea.common.utils import round_datetime 
 22  from haizea.cli.optionparser import Option 
 23  from haizea.cli import Command 
 24  import xmlrpclib 
 25  import sys 
 26  from mx.DateTime import ISO, now, DateTimeDelta, Parser 
 27   
 28  try: 
 29      import xml.etree.ElementTree as ET 
 30  except ImportError: 
 31      # Compatibility with Python <=2.4 
 32      import elementtree.ElementTree as ET  
 33   
34 -class RPCCommand(Command):
35 - def __init__(self, argv):
36 Command.__init__(self, argv) 37 self.optparser.add_option(Option("-s", "--server", action="store", type="string", dest="server", default=defaults.RPC_URI, 38 help = """ 39 Haizea RPC server URI. If not specified, the default %s is used 40 """ % defaults.RPC_URI))
41
42 - def create_rpc_proxy(self, server):
43 return xmlrpclib.ServerProxy(server, allow_none=True)
44
45 -class haizea_request_lease(RPCCommand):
46 """ 47 Requests a new lease. 48 """ 49 50 name = "haizea-request-lease" 51 52 START_NOW = "now" 53 START_BESTEFFORT = "best_effort" 54 DURATION_UNLIMITED = "unlimited" 55
56 - def __init__(self, argv):
57 RPCCommand.__init__(self, argv) 58 59 self.optparser.add_option(Option("-f", "--file", action="store", type="string", dest="file", 60 help = """ 61 File containing a lease description in XML. 62 """)) 63 self.optparser.add_option(Option("-t", "--start", action="store", type="string", dest="start", 64 help = """ 65 Starting time. Can be an ISO timestamp, "best_effort", or "now" 66 """)) 67 self.optparser.add_option(Option("-d", "--duration", action="store", type="string", dest="duration", 68 help = """ 69 Duration. Can be an ISO timestamp or "unlimited" 70 """)) 71 self.optparser.add_option(Option("-n", "--numnodes", action="store", type="int", dest="numnodes", 72 help = """ 73 Number of nodes. 74 """)) 75 self.optparser.add_option(Option("--preemptible", action="store_true", dest="preemptible", 76 help = """ 77 Specifies a preemptible lease. 78 """)) 79 self.optparser.add_option(Option("--non-preemptible", action="store_false", dest="preemptible", 80 help = """ 81 Specifies a non-preemptible lease. 82 """)) 83 self.optparser.add_option(Option("-c", "--cpu", action="store", type="int", dest="cpu", 84 help = """ 85 Percentage of CPU (must be 0 < c <= 100) 86 """)) 87 self.optparser.add_option(Option("-m", "--mem", action="store", type="int", dest="mem", 88 help = """ 89 Memory per node (in MB) 90 """)) 91 self.optparser.add_option(Option("-i", "--vmimage", action="store", type="string", dest="vmimage", 92 help = """ 93 Disk image identifier. 94 """)) 95 self.optparser.add_option(Option("-z", "--vmimagesize", action="store", type="int", dest="vmimagesize", 96 help = """ 97 Disk image size. 98 """))
99
100 - def run(self):
101 self.parse_options() 102 103 if self.opt.file != None: 104 lease_elem = ET.parse(self.opt.file).getroot() 105 # If a relative starting time is used, replace for an 106 # absolute starting time. 107 exact = lease.find("start/exact") 108 if exact != None: 109 exact_time = exact.get("time") 110 exact.set("time", str(self.__absolute_time(exact_time))) 111 lease_xml_str = ET.tostring(lease_elem) 112 else: 113 if self.opt.preemptible == None: 114 preemptible = False 115 else: 116 preemptible = self.opt.preemptible 117 118 capacity = Capacity([constants.RES_CPU, constants.RES_MEM]) 119 capacity.set_quantity(constants.RES_CPU, int(self.opt.cpu) * 100) 120 capacity.set_quantity(constants.RES_MEM, int(self.opt.mem)) 121 requested_resources = dict([(i+1, capacity) for i in range(self.opt.numnodes)]) 122 if self.opt.duration == haizea_request_lease.DURATION_UNLIMITED: 123 # This is an interim solution (make it run for a century). 124 # TODO: Integrate concept of unlimited duration in the lease datastruct 125 duration = DateTimeDelta(36500) 126 else: 127 duration = ISO.ParseTimeDelta(self.opt.duration) 128 129 if self.opt.start == haizea_request_lease.START_NOW: 130 lease = Lease(lease_id = None, 131 submit_time = None, 132 requested_resources = requested_resources, 133 start = Timestamp(Timestamp.NOW), 134 duration = Duration(duration), 135 deadline = None, 136 preemptible=preemptible, 137 software = DiskImageSoftwareEnvironment(self.opt.vmimage, self.opt.vmimagesize), 138 state = None 139 ) 140 elif self.opt.start == haizea_request_lease.START_BESTEFFORT: 141 lease = Lease(lease_id = None, 142 submit_time = None, 143 requested_resources = requested_resources, 144 start = Timestamp(Timestamp.UNSPECIFIED), 145 duration = Duration(duration), 146 deadline = None, 147 preemptible=preemptible, 148 software = DiskImageSoftwareEnvironment(self.opt.vmimage, self.opt.vmimagesize), 149 state = None 150 ) 151 else: 152 start = self.__absolute_time(self.opt.start) 153 lease = Lease(lease_id = None, 154 submit_time = None, 155 requested_resources = requested_resources, 156 start = Timestamp(start), 157 duration = Duration(duration), 158 deadline = None, 159 preemptible=preemptible, 160 software = DiskImageSoftwareEnvironment(self.opt.vmimage, self.opt.vmimagesize), 161 state = None 162 ) 163 164 lease_xml_str = ET.tostring(lease.to_xml()) 165 166 server = self.create_rpc_proxy(self.opt.server) 167 168 try: 169 lease_id = server.create_lease(lease_xml_str) 170 print "Lease submitted correctly." 171 print "Lease ID: %i" % lease_id 172 except xmlrpclib.Fault, err: 173 print >> sys.stderr, "XMLRPC fault: %s" % err.faultString 174 if self.opt.debug: 175 raise 176 except Exception, msg: 177 print >> sys.stderr, "Error: %s" % msg 178 if self.opt.debug: 179 raise
180
181 - def __absolute_time(self, time_str):
182 if time_str[0] == "+": 183 # Relative time 184 time = round_datetime(now() + ISO.ParseTime(time_str[1:])) 185 else: 186 time = Parser.ParseDateTime(time_str) 187 188 return time
189
190 -class haizea_cancel_lease(RPCCommand):
191 """ 192 Cancel a lease. 193 """ 194 195 name = "haizea-cancel-lease" 196
197 - def __init__(self, argv):
198 RPCCommand.__init__(self, argv) 199 200 self.optparser.add_option(Option("-l", "--lease", action="store", type="int", dest="lease", 201 help = """ 202 ID of lease to cancel. 203 """))
204
205 - def run(self):
206 self.parse_options() 207 208 server = self.create_rpc_proxy(self.opt.server) 209 210 try: 211 code = server.cancel_lease(self.opt.lease) 212 except xmlrpclib.Fault, err: 213 print >> sys.stderr, "XMLRPC fault: %s" % err.faultString 214 if self.opt.debug: 215 raise 216 except Exception, msg: 217 print >> sys.stderr, "Error: %s" % msg 218 if self.opt.debug: 219 raise
220 221
222 -class haizea_list_leases(RPCCommand):
223 """ 224 List all active leases in the system (i.e., not including completed or cancelled leases) 225 """ 226 227 name = "haizea-list-leases" 228
229 - def __init__(self, argv):
230 RPCCommand.__init__(self, argv)
231
232 - def run(self):
233 self.parse_options() 234 235 server = self.create_rpc_proxy(self.opt.server) 236 237 fields = [("id","ID", 3), 238 ("type","Type", 12), 239 ("state","State", 9), 240 ("start_req", "Starting time", 22), 241 ("duration_req", "Duration", 12), 242 ("numnodes", "Nodes", 3)] 243 244 try: 245 leases = server.get_leases() 246 leases_fields = [] 247 for lease_xml in leases: 248 lease = Lease.from_xml_string(lease_xml) 249 lease_fields = {} 250 lease_fields["id"] = lease.id 251 lease_fields["type"] = Lease.type_str[lease.get_type()] 252 lease_fields["state"] = Lease.state_str[lease.get_state()] 253 lease_fields["start_req"] = lease.start.requested 254 lease_fields["duration_req"] = lease.duration.requested 255 lease_fields["numnodes"] = len(lease.requested_resources) 256 leases_fields.append(lease_fields) 257 console_table_printer(fields, leases_fields) 258 except xmlrpclib.Fault, err: 259 print >> sys.stderr, "XMLRPC fault: %s" % err.faultString 260 if self.opt.debug: 261 raise 262 except Exception, msg: 263 print >> sys.stderr, "Error: %s" % msg 264 if self.opt.debug: 265 raise
266 267
268 -class haizea_list_hosts(RPCCommand):
269 """ 270 List hosts managed by Haizea 271 """ 272 273 name = "haizea-list-hosts" 274
275 - def __init__(self, argv):
276 RPCCommand.__init__(self, argv)
277
278 - def run(self):
279 self.parse_options() 280 281 server = self.create_rpc_proxy(self.opt.server) 282 283 fields = [("id","ID", 3), 284 ("hostname","Hostname", 10), 285 ("cpu","CPUs", 6), 286 ("mem", "Mem", 6)] 287 288 try: 289 hosts = server.get_hosts() 290 console_table_printer(fields, hosts) 291 except xmlrpclib.Fault, err: 292 print >> sys.stderr, "XMLRPC fault: %s" % err.faultString 293 if self.opt.debug: 294 raise 295 except Exception, msg: 296 print >> sys.stderr, "Error: %s" % msg 297 if self.opt.debug: 298 raise
299
300 -class haizea_show_queue(RPCCommand):
301 """ 302 Show the contents of the Haizea queue 303 """ 304 305 name = "haizea-show-queue" 306
307 - def __init__(self, argv):
308 RPCCommand.__init__(self, argv)
309
310 - def run(self):
311 self.parse_options() 312 313 server = self.create_rpc_proxy(self.opt.server) 314 315 fields = [("id","ID", 3), 316 ("type","Type", 12), 317 ("state","State", 9), 318 ("start_req", "Starting time", 22), 319 ("duration_req", "Duration", 12), 320 ("numnodes", "Nodes", 3)] 321 322 try: 323 leases = server.get_queue() 324 if len(leases) == 0: 325 print "Queue is empty." 326 else: 327 leases_fields = [] 328 for lease_xml in leases: 329 lease = Lease.from_xml_string(lease_xml) 330 lease_fields = {} 331 lease_fields["id"] = lease.id 332 lease_fields["type"] = Lease.type_str[lease.get_type()] 333 lease_fields["state"] = Lease.state_str[lease.get_state()] 334 lease_fields["start_req"] = lease.start.requested 335 lease_fields["duration_req"] = lease.duration.requested 336 lease_fields["numnodes"] = len(lease.requested_resources) 337 leases_fields.append(lease_fields) 338 console_table_printer(fields, leases_fields) 339 except xmlrpclib.Fault, err: 340 print >> sys.stderr, "XMLRPC fault: %s" % err.faultString 341 if self.opt.debug: 342 raise 343 except Exception, msg: 344 print >> sys.stderr, "Error: %s" % msg 345 if self.opt.debug: 346 raise
347 348
349 -def console_table_printer(fields, values):
350 print "\33[1m\33[4m", 351 for (name,pname,width) in fields: 352 width = max(len(pname),width) + 1 353 centered = pname.ljust(width) 354 print centered, 355 print "\33[0m" 356 for v in values: 357 for (name,pname,width) in fields: 358 width = max(len(name),width) 359 print " %s" % str(v[name]).ljust(width), 360 print
361