def __init__(self, name, password, connection, hd_image, base_image=None, xml=None, **kwargs): AbstractLatentBuildWorker.__init__(self, name, password, **kwargs) if not libvirt: config.error("The python module 'libvirt' is needed to use a LibVirtWorker") self.connection = connection self.image = hd_image self.base_image = base_image self.xml = xml self.cheap_copy = True self.graceful_shutdown = False self.domain = None self.ready = False self._find_existing_deferred = self._find_existing_instance()
def __init__(self, name, password, instance_type, ami=None, valid_ami_owners=None, valid_ami_location_regex=None, elastic_ip=None, identifier=None, secret_identifier=None, aws_id_file_path=None, user_data=None, region=None, keypair_name='latent_buildbot_worker', security_name='latent_buildbot_worker', spot_instance=False, max_spot_price=1.6, volumes=None, placement=None, price_multiplier=1.2, tags=None, retry=1, retry_price_adjustment=1, product_description='Linux/UNIX', **kwargs): if not boto: config.error("The python module 'boto' is needed to use a " "EC2LatentBuildWorker") if volumes is None: volumes = [] if tags is None: tags = {} AbstractLatentBuildWorker.__init__(self, name, password, **kwargs) if not ((ami is not None) ^ (valid_ami_owners is not None or valid_ami_location_regex is not None)): raise ValueError( 'You must provide either a specific ami, or one or both of ' 'valid_ami_location_regex and valid_ami_owners') self.ami = ami if valid_ami_owners is not None: if isinstance(valid_ami_owners, (int, long)): valid_ami_owners = (valid_ami_owners,) else: for element in valid_ami_owners: if not isinstance(element, (int, long)): raise ValueError( 'valid_ami_owners should be int or iterable ' 'of ints', element) if valid_ami_location_regex is not None: if not isinstance(valid_ami_location_regex, basestring): raise ValueError( 'valid_ami_location_regex should be a string') else: # verify that regex will compile re.compile(valid_ami_location_regex) self.valid_ami_owners = valid_ami_owners self.valid_ami_location_regex = valid_ami_location_regex self.instance_type = instance_type self.keypair_name = keypair_name self.security_name = security_name self.user_data = user_data self.spot_instance = spot_instance self.max_spot_price = max_spot_price self.volumes = volumes self.price_multiplier = price_multiplier self.retry_price_adjustment = retry_price_adjustment self.retry = retry self.attempt = 1 self.product_description = product_description if None not in [placement, region]: self.placement = '%s%s' % (region, placement) else: self.placement = None if identifier is None: assert secret_identifier is None, ( 'supply both or neither of identifier, secret_identifier') if aws_id_file_path is None: home = os.environ['HOME'] default_path = os.path.join(home, '.ec2', 'aws_id') if os.path.exists(default_path): aws_id_file_path = default_path if aws_id_file_path: log.msg('WARNING: EC2LatentBuildWorker is using deprecated ' 'aws_id file') with open(aws_id_file_path, 'r') as aws_file: identifier = aws_file.readline().strip() secret_identifier = aws_file.readline().strip() else: assert aws_id_file_path is None, \ 'if you supply the identifier and secret_identifier, ' \ 'do not specify the aws_id_file_path' assert secret_identifier is not None, \ 'supply both or neither of identifier, secret_identifier' region_found = None # Make the EC2 connection. if region is not None: for r in boto.ec2.regions(aws_access_key_id=identifier, aws_secret_access_key=secret_identifier): if r.name == region: region_found = r if region_found is not None: self.conn = boto.ec2.connect_to_region(region, aws_access_key_id=identifier, aws_secret_access_key=secret_identifier) else: raise ValueError( 'The specified region does not exist: ' + region) else: self.conn = boto.connect_ec2(identifier, secret_identifier) # Make a keypair # # We currently discard the keypair data because we don't need it. # If we do need it in the future, we will always recreate the keypairs # because there is no way to # programmatically retrieve the private key component, unless we # generate it and store it on the filesystem, which is an unnecessary # usage requirement. try: key_pair = self.conn.get_all_key_pairs(keypair_name)[0] assert key_pair # key_pair.delete() # would be used to recreate except boto.exception.EC2ResponseError as e: if 'InvalidKeyPair.NotFound' not in e.body: if 'AuthFailure' in e.body: log.msg('POSSIBLE CAUSES OF ERROR:\n' ' Did you supply your AWS credentials?\n' ' Did you sign up for EC2?\n' ' Did you put a credit card number in your AWS ' 'account?\n' 'Please doublecheck before reporting a problem.\n') raise # make one; we would always do this, and stash the result, if we # needed the key (for instance, to SSH to the box). We'd then # use paramiko to use the key to connect. self.conn.create_key_pair(keypair_name) # create security group try: group = self.conn.get_all_security_groups(security_name)[0] assert group except boto.exception.EC2ResponseError as e: if 'InvalidGroup.NotFound' in e.body: self.security_group = self.conn.create_security_group( security_name, 'Authorization to access the buildbot instance.') # Authorize the master as necessary # TODO this is where we'd open the hole to do the reverse pb # connect to the buildbot # ip = urllib.urlopen( # 'http://checkip.amazonaws.com').read().strip() # self.security_group.authorize('tcp', 22, 22, '%s/32' % ip) # self.security_group.authorize('tcp', 80, 80, '%s/32' % ip) else: raise # get the image if self.ami is not None: self.image = self.conn.get_image(self.ami) else: # verify we have access to at least one acceptable image discard = self.get_image() assert discard # get the specified elastic IP, if any if elastic_ip is not None: elastic_ip = self.conn.get_all_addresses([elastic_ip])[0] self.elastic_ip = elastic_ip self.tags = tags