Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/boto/manage/server.py @ 0:d30785e31577 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
| author | guerler |
|---|---|
| date | Fri, 31 Jul 2020 00:18:57 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:d30785e31577 |
|---|---|
| 1 # Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ | |
| 2 # Copyright (c) 2010 Chris Moyer http://coredumped.org/ | |
| 3 # | |
| 4 # Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 # copy of this software and associated documentation files (the | |
| 6 # "Software"), to deal in the Software without restriction, including | |
| 7 # without limitation the rights to use, copy, modify, merge, publish, dis- | |
| 8 # tribute, sublicense, and/or sell copies of the Software, and to permit | |
| 9 # persons to whom the Software is furnished to do so, subject to the fol- | |
| 10 # lowing conditions: | |
| 11 # | |
| 12 # The above copyright notice and this permission notice shall be included | |
| 13 # in all copies or substantial portions of the Software. | |
| 14 # | |
| 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 16 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- | |
| 17 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT | |
| 18 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
| 19 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
| 21 # IN THE SOFTWARE. | |
| 22 """ | |
| 23 High-level abstraction of an EC2 server | |
| 24 """ | |
| 25 | |
| 26 import boto.ec2 | |
| 27 from boto.mashups.iobject import IObject | |
| 28 from boto.pyami.config import BotoConfigPath, Config | |
| 29 from boto.sdb.db.model import Model | |
| 30 from boto.sdb.db.property import StringProperty, IntegerProperty, BooleanProperty, CalculatedProperty | |
| 31 from boto.manage import propget | |
| 32 from boto.ec2.zone import Zone | |
| 33 from boto.ec2.keypair import KeyPair | |
| 34 import os, time | |
| 35 from contextlib import closing | |
| 36 from boto.exception import EC2ResponseError | |
| 37 from boto.compat import six, StringIO | |
| 38 | |
| 39 InstanceTypes = ['m1.small', 'm1.large', 'm1.xlarge', | |
| 40 'c1.medium', 'c1.xlarge', | |
| 41 'm2.2xlarge', 'm2.4xlarge'] | |
| 42 | |
| 43 class Bundler(object): | |
| 44 | |
| 45 def __init__(self, server, uname='root'): | |
| 46 from boto.manage.cmdshell import SSHClient | |
| 47 self.server = server | |
| 48 self.uname = uname | |
| 49 self.ssh_client = SSHClient(server, uname=uname) | |
| 50 | |
| 51 def copy_x509(self, key_file, cert_file): | |
| 52 print('\tcopying cert and pk over to /mnt directory on server') | |
| 53 self.ssh_client.open_sftp() | |
| 54 path, name = os.path.split(key_file) | |
| 55 self.remote_key_file = '/mnt/%s' % name | |
| 56 self.ssh_client.put_file(key_file, self.remote_key_file) | |
| 57 path, name = os.path.split(cert_file) | |
| 58 self.remote_cert_file = '/mnt/%s' % name | |
| 59 self.ssh_client.put_file(cert_file, self.remote_cert_file) | |
| 60 print('...complete!') | |
| 61 | |
| 62 def bundle_image(self, prefix, size, ssh_key): | |
| 63 command = "" | |
| 64 if self.uname != 'root': | |
| 65 command = "sudo " | |
| 66 command += 'ec2-bundle-vol ' | |
| 67 command += '-c %s -k %s ' % (self.remote_cert_file, self.remote_key_file) | |
| 68 command += '-u %s ' % self.server._reservation.owner_id | |
| 69 command += '-p %s ' % prefix | |
| 70 command += '-s %d ' % size | |
| 71 command += '-d /mnt ' | |
| 72 if self.server.instance_type == 'm1.small' or self.server.instance_type == 'c1.medium': | |
| 73 command += '-r i386' | |
| 74 else: | |
| 75 command += '-r x86_64' | |
| 76 return command | |
| 77 | |
| 78 def upload_bundle(self, bucket, prefix, ssh_key): | |
| 79 command = "" | |
| 80 if self.uname != 'root': | |
| 81 command = "sudo " | |
| 82 command += 'ec2-upload-bundle ' | |
| 83 command += '-m /mnt/%s.manifest.xml ' % prefix | |
| 84 command += '-b %s ' % bucket | |
| 85 command += '-a %s ' % self.server.ec2.aws_access_key_id | |
| 86 command += '-s %s ' % self.server.ec2.aws_secret_access_key | |
| 87 return command | |
| 88 | |
| 89 def bundle(self, bucket=None, prefix=None, key_file=None, cert_file=None, | |
| 90 size=None, ssh_key=None, fp=None, clear_history=True): | |
| 91 iobject = IObject() | |
| 92 if not bucket: | |
| 93 bucket = iobject.get_string('Name of S3 bucket') | |
| 94 if not prefix: | |
| 95 prefix = iobject.get_string('Prefix for AMI file') | |
| 96 if not key_file: | |
| 97 key_file = iobject.get_filename('Path to RSA private key file') | |
| 98 if not cert_file: | |
| 99 cert_file = iobject.get_filename('Path to RSA public cert file') | |
| 100 if not size: | |
| 101 size = iobject.get_int('Size (in MB) of bundled image') | |
| 102 if not ssh_key: | |
| 103 ssh_key = self.server.get_ssh_key_file() | |
| 104 self.copy_x509(key_file, cert_file) | |
| 105 if not fp: | |
| 106 fp = StringIO() | |
| 107 fp.write('sudo mv %s /mnt/boto.cfg; ' % BotoConfigPath) | |
| 108 fp.write('mv ~/.ssh/authorized_keys /mnt/authorized_keys; ') | |
| 109 if clear_history: | |
| 110 fp.write('history -c; ') | |
| 111 fp.write(self.bundle_image(prefix, size, ssh_key)) | |
| 112 fp.write('; ') | |
| 113 fp.write(self.upload_bundle(bucket, prefix, ssh_key)) | |
| 114 fp.write('; ') | |
| 115 fp.write('sudo mv /mnt/boto.cfg %s; ' % BotoConfigPath) | |
| 116 fp.write('mv /mnt/authorized_keys ~/.ssh/authorized_keys') | |
| 117 command = fp.getvalue() | |
| 118 print('running the following command on the remote server:') | |
| 119 print(command) | |
| 120 t = self.ssh_client.run(command) | |
| 121 print('\t%s' % t[0]) | |
| 122 print('\t%s' % t[1]) | |
| 123 print('...complete!') | |
| 124 print('registering image...') | |
| 125 self.image_id = self.server.ec2.register_image(name=prefix, image_location='%s/%s.manifest.xml' % (bucket, prefix)) | |
| 126 return self.image_id | |
| 127 | |
| 128 class CommandLineGetter(object): | |
| 129 | |
| 130 def get_ami_list(self): | |
| 131 my_amis = [] | |
| 132 for ami in self.ec2.get_all_images(): | |
| 133 # hack alert, need a better way to do this! | |
| 134 if ami.location.find('pyami') >= 0: | |
| 135 my_amis.append((ami.location, ami)) | |
| 136 return my_amis | |
| 137 | |
| 138 def get_region(self, params): | |
| 139 region = params.get('region', None) | |
| 140 if isinstance(region, basestring): | |
| 141 region = boto.ec2.get_region(region) | |
| 142 params['region'] = region | |
| 143 if not region: | |
| 144 prop = self.cls.find_property('region_name') | |
| 145 params['region'] = propget.get(prop, choices=boto.ec2.regions) | |
| 146 self.ec2 = params['region'].connect() | |
| 147 | |
| 148 def get_name(self, params): | |
| 149 if not params.get('name', None): | |
| 150 prop = self.cls.find_property('name') | |
| 151 params['name'] = propget.get(prop) | |
| 152 | |
| 153 def get_description(self, params): | |
| 154 if not params.get('description', None): | |
| 155 prop = self.cls.find_property('description') | |
| 156 params['description'] = propget.get(prop) | |
| 157 | |
| 158 def get_instance_type(self, params): | |
| 159 if not params.get('instance_type', None): | |
| 160 prop = StringProperty(name='instance_type', verbose_name='Instance Type', | |
| 161 choices=InstanceTypes) | |
| 162 params['instance_type'] = propget.get(prop) | |
| 163 | |
| 164 def get_quantity(self, params): | |
| 165 if not params.get('quantity', None): | |
| 166 prop = IntegerProperty(name='quantity', verbose_name='Number of Instances') | |
| 167 params['quantity'] = propget.get(prop) | |
| 168 | |
| 169 def get_zone(self, params): | |
| 170 if not params.get('zone', None): | |
| 171 prop = StringProperty(name='zone', verbose_name='EC2 Availability Zone', | |
| 172 choices=self.ec2.get_all_zones) | |
| 173 params['zone'] = propget.get(prop) | |
| 174 | |
| 175 def get_ami_id(self, params): | |
| 176 valid = False | |
| 177 while not valid: | |
| 178 ami = params.get('ami', None) | |
| 179 if not ami: | |
| 180 prop = StringProperty(name='ami', verbose_name='AMI') | |
| 181 ami = propget.get(prop) | |
| 182 try: | |
| 183 rs = self.ec2.get_all_images([ami]) | |
| 184 if len(rs) == 1: | |
| 185 valid = True | |
| 186 params['ami'] = rs[0] | |
| 187 except EC2ResponseError: | |
| 188 pass | |
| 189 | |
| 190 def get_group(self, params): | |
| 191 group = params.get('group', None) | |
| 192 if isinstance(group, basestring): | |
| 193 group_list = self.ec2.get_all_security_groups() | |
| 194 for g in group_list: | |
| 195 if g.name == group: | |
| 196 group = g | |
| 197 params['group'] = g | |
| 198 if not group: | |
| 199 prop = StringProperty(name='group', verbose_name='EC2 Security Group', | |
| 200 choices=self.ec2.get_all_security_groups) | |
| 201 params['group'] = propget.get(prop) | |
| 202 | |
| 203 def get_key(self, params): | |
| 204 keypair = params.get('keypair', None) | |
| 205 if isinstance(keypair, basestring): | |
| 206 key_list = self.ec2.get_all_key_pairs() | |
| 207 for k in key_list: | |
| 208 if k.name == keypair: | |
| 209 keypair = k.name | |
| 210 params['keypair'] = k.name | |
| 211 if not keypair: | |
| 212 prop = StringProperty(name='keypair', verbose_name='EC2 KeyPair', | |
| 213 choices=self.ec2.get_all_key_pairs) | |
| 214 params['keypair'] = propget.get(prop).name | |
| 215 | |
| 216 def get(self, cls, params): | |
| 217 self.cls = cls | |
| 218 self.get_region(params) | |
| 219 self.ec2 = params['region'].connect() | |
| 220 self.get_name(params) | |
| 221 self.get_description(params) | |
| 222 self.get_instance_type(params) | |
| 223 self.get_zone(params) | |
| 224 self.get_quantity(params) | |
| 225 self.get_ami_id(params) | |
| 226 self.get_group(params) | |
| 227 self.get_key(params) | |
| 228 | |
| 229 class Server(Model): | |
| 230 | |
| 231 # | |
| 232 # The properties of this object consists of real properties for data that | |
| 233 # is not already stored in EC2 somewhere (e.g. name, description) plus | |
| 234 # calculated properties for all of the properties that are already in | |
| 235 # EC2 (e.g. hostname, security groups, etc.) | |
| 236 # | |
| 237 name = StringProperty(unique=True, verbose_name="Name") | |
| 238 description = StringProperty(verbose_name="Description") | |
| 239 region_name = StringProperty(verbose_name="EC2 Region Name") | |
| 240 instance_id = StringProperty(verbose_name="EC2 Instance ID") | |
| 241 elastic_ip = StringProperty(verbose_name="EC2 Elastic IP Address") | |
| 242 production = BooleanProperty(verbose_name="Is This Server Production", default=False) | |
| 243 ami_id = CalculatedProperty(verbose_name="AMI ID", calculated_type=str, use_method=True) | |
| 244 zone = CalculatedProperty(verbose_name="Availability Zone Name", calculated_type=str, use_method=True) | |
| 245 hostname = CalculatedProperty(verbose_name="Public DNS Name", calculated_type=str, use_method=True) | |
| 246 private_hostname = CalculatedProperty(verbose_name="Private DNS Name", calculated_type=str, use_method=True) | |
| 247 groups = CalculatedProperty(verbose_name="Security Groups", calculated_type=list, use_method=True) | |
| 248 security_group = CalculatedProperty(verbose_name="Primary Security Group Name", calculated_type=str, use_method=True) | |
| 249 key_name = CalculatedProperty(verbose_name="Key Name", calculated_type=str, use_method=True) | |
| 250 instance_type = CalculatedProperty(verbose_name="Instance Type", calculated_type=str, use_method=True) | |
| 251 status = CalculatedProperty(verbose_name="Current Status", calculated_type=str, use_method=True) | |
| 252 launch_time = CalculatedProperty(verbose_name="Server Launch Time", calculated_type=str, use_method=True) | |
| 253 console_output = CalculatedProperty(verbose_name="Console Output", calculated_type=open, use_method=True) | |
| 254 | |
| 255 packages = [] | |
| 256 plugins = [] | |
| 257 | |
| 258 @classmethod | |
| 259 def add_credentials(cls, cfg, aws_access_key_id, aws_secret_access_key): | |
| 260 if not cfg.has_section('Credentials'): | |
| 261 cfg.add_section('Credentials') | |
| 262 cfg.set('Credentials', 'aws_access_key_id', aws_access_key_id) | |
| 263 cfg.set('Credentials', 'aws_secret_access_key', aws_secret_access_key) | |
| 264 if not cfg.has_section('DB_Server'): | |
| 265 cfg.add_section('DB_Server') | |
| 266 cfg.set('DB_Server', 'db_type', 'SimpleDB') | |
| 267 cfg.set('DB_Server', 'db_name', cls._manager.domain.name) | |
| 268 | |
| 269 @classmethod | |
| 270 def create(cls, config_file=None, logical_volume = None, cfg = None, **params): | |
| 271 """ | |
| 272 Create a new instance based on the specified configuration file or the specified | |
| 273 configuration and the passed in parameters. | |
| 274 | |
| 275 If the config_file argument is not None, the configuration is read from there. | |
| 276 Otherwise, the cfg argument is used. | |
| 277 | |
| 278 The config file may include other config files with a #import reference. The included | |
| 279 config files must reside in the same directory as the specified file. | |
| 280 | |
| 281 The logical_volume argument, if supplied, will be used to get the current physical | |
| 282 volume ID and use that as an override of the value specified in the config file. This | |
| 283 may be useful for debugging purposes when you want to debug with a production config | |
| 284 file but a test Volume. | |
| 285 | |
| 286 The dictionary argument may be used to override any EC2 configuration values in the | |
| 287 config file. | |
| 288 """ | |
| 289 if config_file: | |
| 290 cfg = Config(path=config_file) | |
| 291 if cfg.has_section('EC2'): | |
| 292 # include any EC2 configuration values that aren't specified in params: | |
| 293 for option in cfg.options('EC2'): | |
| 294 if option not in params: | |
| 295 params[option] = cfg.get('EC2', option) | |
| 296 getter = CommandLineGetter() | |
| 297 getter.get(cls, params) | |
| 298 region = params.get('region') | |
| 299 ec2 = region.connect() | |
| 300 cls.add_credentials(cfg, ec2.aws_access_key_id, ec2.aws_secret_access_key) | |
| 301 ami = params.get('ami') | |
| 302 kp = params.get('keypair') | |
| 303 group = params.get('group') | |
| 304 zone = params.get('zone') | |
| 305 # deal with possibly passed in logical volume: | |
| 306 if logical_volume != None: | |
| 307 cfg.set('EBS', 'logical_volume_name', logical_volume.name) | |
| 308 cfg_fp = StringIO() | |
| 309 cfg.write(cfg_fp) | |
| 310 # deal with the possibility that zone and/or keypair are strings read from the config file: | |
| 311 if isinstance(zone, Zone): | |
| 312 zone = zone.name | |
| 313 if isinstance(kp, KeyPair): | |
| 314 kp = kp.name | |
| 315 reservation = ami.run(min_count=1, | |
| 316 max_count=params.get('quantity', 1), | |
| 317 key_name=kp, | |
| 318 security_groups=[group], | |
| 319 instance_type=params.get('instance_type'), | |
| 320 placement = zone, | |
| 321 user_data = cfg_fp.getvalue()) | |
| 322 l = [] | |
| 323 i = 0 | |
| 324 elastic_ip = params.get('elastic_ip') | |
| 325 instances = reservation.instances | |
| 326 if elastic_ip is not None and instances.__len__() > 0: | |
| 327 instance = instances[0] | |
| 328 print('Waiting for instance to start so we can set its elastic IP address...') | |
| 329 # Sometimes we get a message from ec2 that says that the instance does not exist. | |
| 330 # Hopefully the following delay will giv eec2 enough time to get to a stable state: | |
| 331 time.sleep(5) | |
| 332 while instance.update() != 'running': | |
| 333 time.sleep(1) | |
| 334 instance.use_ip(elastic_ip) | |
| 335 print('set the elastic IP of the first instance to %s' % elastic_ip) | |
| 336 for instance in instances: | |
| 337 s = cls() | |
| 338 s.ec2 = ec2 | |
| 339 s.name = params.get('name') + '' if i==0 else str(i) | |
| 340 s.description = params.get('description') | |
| 341 s.region_name = region.name | |
| 342 s.instance_id = instance.id | |
| 343 if elastic_ip and i == 0: | |
| 344 s.elastic_ip = elastic_ip | |
| 345 s.put() | |
| 346 l.append(s) | |
| 347 i += 1 | |
| 348 return l | |
| 349 | |
| 350 @classmethod | |
| 351 def create_from_instance_id(cls, instance_id, name, description=''): | |
| 352 regions = boto.ec2.regions() | |
| 353 for region in regions: | |
| 354 ec2 = region.connect() | |
| 355 try: | |
| 356 rs = ec2.get_all_reservations([instance_id]) | |
| 357 except: | |
| 358 rs = [] | |
| 359 if len(rs) == 1: | |
| 360 s = cls() | |
| 361 s.ec2 = ec2 | |
| 362 s.name = name | |
| 363 s.description = description | |
| 364 s.region_name = region.name | |
| 365 s.instance_id = instance_id | |
| 366 s._reservation = rs[0] | |
| 367 for instance in s._reservation.instances: | |
| 368 if instance.id == instance_id: | |
| 369 s._instance = instance | |
| 370 s.put() | |
| 371 return s | |
| 372 return None | |
| 373 | |
| 374 @classmethod | |
| 375 def create_from_current_instances(cls): | |
| 376 servers = [] | |
| 377 regions = boto.ec2.regions() | |
| 378 for region in regions: | |
| 379 ec2 = region.connect() | |
| 380 rs = ec2.get_all_reservations() | |
| 381 for reservation in rs: | |
| 382 for instance in reservation.instances: | |
| 383 try: | |
| 384 next(Server.find(instance_id=instance.id)) | |
| 385 boto.log.info('Server for %s already exists' % instance.id) | |
| 386 except StopIteration: | |
| 387 s = cls() | |
| 388 s.ec2 = ec2 | |
| 389 s.name = instance.id | |
| 390 s.region_name = region.name | |
| 391 s.instance_id = instance.id | |
| 392 s._reservation = reservation | |
| 393 s.put() | |
| 394 servers.append(s) | |
| 395 return servers | |
| 396 | |
| 397 def __init__(self, id=None, **kw): | |
| 398 super(Server, self).__init__(id, **kw) | |
| 399 self.ssh_key_file = None | |
| 400 self.ec2 = None | |
| 401 self._cmdshell = None | |
| 402 self._reservation = None | |
| 403 self._instance = None | |
| 404 self._setup_ec2() | |
| 405 | |
| 406 def _setup_ec2(self): | |
| 407 if self.ec2 and self._instance and self._reservation: | |
| 408 return | |
| 409 if self.id: | |
| 410 if self.region_name: | |
| 411 for region in boto.ec2.regions(): | |
| 412 if region.name == self.region_name: | |
| 413 self.ec2 = region.connect() | |
| 414 if self.instance_id and not self._instance: | |
| 415 try: | |
| 416 rs = self.ec2.get_all_reservations([self.instance_id]) | |
| 417 if len(rs) >= 1: | |
| 418 for instance in rs[0].instances: | |
| 419 if instance.id == self.instance_id: | |
| 420 self._reservation = rs[0] | |
| 421 self._instance = instance | |
| 422 except EC2ResponseError: | |
| 423 pass | |
| 424 | |
| 425 def _status(self): | |
| 426 status = '' | |
| 427 if self._instance: | |
| 428 self._instance.update() | |
| 429 status = self._instance.state | |
| 430 return status | |
| 431 | |
| 432 def _hostname(self): | |
| 433 hostname = '' | |
| 434 if self._instance: | |
| 435 hostname = self._instance.public_dns_name | |
| 436 return hostname | |
| 437 | |
| 438 def _private_hostname(self): | |
| 439 hostname = '' | |
| 440 if self._instance: | |
| 441 hostname = self._instance.private_dns_name | |
| 442 return hostname | |
| 443 | |
| 444 def _instance_type(self): | |
| 445 it = '' | |
| 446 if self._instance: | |
| 447 it = self._instance.instance_type | |
| 448 return it | |
| 449 | |
| 450 def _launch_time(self): | |
| 451 lt = '' | |
| 452 if self._instance: | |
| 453 lt = self._instance.launch_time | |
| 454 return lt | |
| 455 | |
| 456 def _console_output(self): | |
| 457 co = '' | |
| 458 if self._instance: | |
| 459 co = self._instance.get_console_output() | |
| 460 return co | |
| 461 | |
| 462 def _groups(self): | |
| 463 gn = [] | |
| 464 if self._reservation: | |
| 465 gn = self._reservation.groups | |
| 466 return gn | |
| 467 | |
| 468 def _security_group(self): | |
| 469 groups = self._groups() | |
| 470 if len(groups) >= 1: | |
| 471 return groups[0].id | |
| 472 return "" | |
| 473 | |
| 474 def _zone(self): | |
| 475 zone = None | |
| 476 if self._instance: | |
| 477 zone = self._instance.placement | |
| 478 return zone | |
| 479 | |
| 480 def _key_name(self): | |
| 481 kn = None | |
| 482 if self._instance: | |
| 483 kn = self._instance.key_name | |
| 484 return kn | |
| 485 | |
| 486 def put(self): | |
| 487 super(Server, self).put() | |
| 488 self._setup_ec2() | |
| 489 | |
| 490 def delete(self): | |
| 491 if self.production: | |
| 492 raise ValueError("Can't delete a production server") | |
| 493 #self.stop() | |
| 494 super(Server, self).delete() | |
| 495 | |
| 496 def stop(self): | |
| 497 if self.production: | |
| 498 raise ValueError("Can't delete a production server") | |
| 499 if self._instance: | |
| 500 self._instance.stop() | |
| 501 | |
| 502 def terminate(self): | |
| 503 if self.production: | |
| 504 raise ValueError("Can't delete a production server") | |
| 505 if self._instance: | |
| 506 self._instance.terminate() | |
| 507 | |
| 508 def reboot(self): | |
| 509 if self._instance: | |
| 510 self._instance.reboot() | |
| 511 | |
| 512 def wait(self): | |
| 513 while self.status != 'running': | |
| 514 time.sleep(5) | |
| 515 | |
| 516 def get_ssh_key_file(self): | |
| 517 if not self.ssh_key_file: | |
| 518 ssh_dir = os.path.expanduser('~/.ssh') | |
| 519 if os.path.isdir(ssh_dir): | |
| 520 ssh_file = os.path.join(ssh_dir, '%s.pem' % self.key_name) | |
| 521 if os.path.isfile(ssh_file): | |
| 522 self.ssh_key_file = ssh_file | |
| 523 if not self.ssh_key_file: | |
| 524 iobject = IObject() | |
| 525 self.ssh_key_file = iobject.get_filename('Path to OpenSSH Key file') | |
| 526 return self.ssh_key_file | |
| 527 | |
| 528 def get_cmdshell(self): | |
| 529 if not self._cmdshell: | |
| 530 from boto.manage import cmdshell | |
| 531 self.get_ssh_key_file() | |
| 532 self._cmdshell = cmdshell.start(self) | |
| 533 return self._cmdshell | |
| 534 | |
| 535 def reset_cmdshell(self): | |
| 536 self._cmdshell = None | |
| 537 | |
| 538 def run(self, command): | |
| 539 with closing(self.get_cmdshell()) as cmd: | |
| 540 status = cmd.run(command) | |
| 541 return status | |
| 542 | |
| 543 def get_bundler(self, uname='root'): | |
| 544 self.get_ssh_key_file() | |
| 545 return Bundler(self, uname) | |
| 546 | |
| 547 def get_ssh_client(self, uname='root', ssh_pwd=None): | |
| 548 from boto.manage.cmdshell import SSHClient | |
| 549 self.get_ssh_key_file() | |
| 550 return SSHClient(self, uname=uname, ssh_pwd=ssh_pwd) | |
| 551 | |
| 552 def install(self, pkg): | |
| 553 return self.run('apt-get -y install %s' % pkg) | |
| 554 | |
| 555 | |
| 556 |
