Beispiel #1
0
def do_build(ctxt, **kwargs):
    conn = ctxt.cnx_ec2
    if 'template' in kwargs and kwargs['template']:
        template_file_name = kwargs['template']
        kwargs = parse_template(ctxt, template_file_name, kwargs)
    del kwargs['template']

    defaultrun = {'instance_type': 'm1.large', 'key_name': ctxt.key_name }
    for key in defaultrun:
        if key not in kwargs or kwargs[key] == None:
            kwargs[key] = defaultrun[key]
                        
    (remote_user, kwargs) = get_remote_user(ctxt, **kwargs)
    (key_file, kwargs) = get_key_file(ctxt, **kwargs)

    (tags,kwargs) = do_tags(**kwargs)

    do_run_scripts =  kwargs.pop('run')

    ###########
    # Check VM naming
    ###########
    if 'Name' not in tags and kwargs['hostname'] is not None:
        tags['Name'] = kwargs['hostname']
    if 'Name' not in tags:
        yield "instance name is mandatory"
        return
    
    try:
        oslib.ec2_objects.Instance(ctxt, name=tags['Name']).get()
        # if get succed, the name already exist, else get throws an exception
        yield "duplicate name %s" % tags['Name']
        return 
    except:
        pass
        
    user_data_properties = {}
    
    image = kwargs.pop('image_id', None)

    ###########
    # Check device mapping
    ###########
    volumes = BlockDeviceMapping(conn)
    first_volume = 'f'
    l = first_volume

    ebs_optimized = False
    for volume_info in kwargs.pop('volume_size', []):
        # yaml is not typed, volume_info can be a string or a number
        if isinstance(volume_info, basestring):
            options = volume_info.split(',')
            size = int(oslib.parse_size(options[0], 'G', default_suffix='G'))
        else:
            options = []
            size = int(volume_info)
        vol_kwargs = {"connection":conn, "size": size}
        if len(options) > 1:
            for opt in options[1:]:
                parsed = opt.split('=')
                key = parsed[0]
                if len(parsed) == 2:
                    value = parsed[1]
                elif len(parsed) == 1:
                    value = True
                else:
                    raise OSLibError("can't parse volume argument %s", opt)
                if key == 'iops':
                    ebs_optimized = True
                    vol_kwargs['volume_type'] = 'io1'
                vol_kwargs[key] = value
        volumes["/dev/sd%s"%l] = BlockDeviceType(**vol_kwargs)
        l = chr( ord(l[0]) + 1)
    kwargs['ebs_optimized'] = ebs_optimized

    # if drive letter is not f, some volumes definition was found
    if l != first_volume:
        kwargs['block_device_map'] = volumes
        user_data_properties['volumes'] = ' '.join(volumes.keys())

    # after user_data_properties['volumes'] otherwise they will be lvm'ed
    for snapshot_id in kwargs.pop('snap_id', []):
        volumes["/dev/sd%s"%l] = BlockDeviceType(connection=conn, snapshot_id=snapshot_id)
        l = chr( ord(l[0]) + 1)
    
    kwargs = build_user_data(user_data_properties, **kwargs)

    ###########
    # Check elastic IP
    ###########
    if kwargs['elastic_ip']:
        eip = True
    else:
        eip = False
    del kwargs['elastic_ip']

    for k in kwargs.keys()[:]:
        value = kwargs[k]
        if kwargs[k] == None:
            del(kwargs[k])
        elif value.__class__ == [].__class__ and len(value) == 0:
            del(kwargs[k])
    
    if 'private_ip_address' in kwargs and kwargs['private_ip_address']:
        netif_specification = NetworkInterfaceCollection()
        netif_kwargs = {}
        if kwargs['private_ip_address']:
            netif_kwargs['private_ip_address'] = kwargs['private_ip_address']
            del kwargs['private_ip_address']
        if 'associate_public_ip_address' in kwargs and kwargs['associate_public_ip_address']:
            netif_kwargs['associate_public_ip_address'] = kwargs['associate_public_ip_address']
            del kwargs['associate_public_ip_address']
        if 'security_groups' in kwargs and kwargs['security_groups']:
            netif_kwargs['groups'] = kwargs['security_groups']
            del kwargs['security_groups']
        
        netif_kwargs['subnet_id'] = kwargs['subnet_id']
        del kwargs['subnet_id']
        print netif_kwargs
        spec = NetworkInterfaceSpecification(**netif_kwargs)
        netif_specification.append(spec)   
        kwargs['network_interfaces'] = netif_specification

    reservation = conn.run_instances(image, **kwargs)
    instance = reservation.instances[0]
    # Quick hack to keep the selected remote user
    instance.remote_user = remote_user
    
    if len(tags) > 0:
        conn.create_tags([ instance.id ], tags)
        
    if instance.interfaces and len(instance.interfaces) > 0:
        for interface in instance.interfaces:
            conn.create_tags([ interface.id ], {'creator': tags['creator']})

    while instance.state != 'running' and instance.state != 'terminated':
        instance.update(True)
        yield (".")
        time.sleep(1)
    yield ("\n")
    
    if eip:
        ip = conn.allocate_address().public_ip
        conn.associate_address(instance_id = instance.id, public_ip=ip)
        conn.create_tags([instance.id], {"EIP": ip})

    #Update tag for this instance's volumes
    for device in instance.block_device_mapping:
        device_type = instance.block_device_mapping[device]
        (vol_tags, vol_kwargs) = do_tags(name='%s/%s' % (tags['Name'], device.replace('/dev/','')))
        conn.create_tags([ device_type.volume_id ], vol_tags)
    instance.update(True)

    windows_instance = instance.platform == 'Windows'

    if do_run_scripts and not windows_instance:
        while instance.state != 'terminated':
            try:
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                s.settimeout(1.0)
                s.connect((instance.public_dns_name, 22))
                s.close()
                break
            except socket.error, msg:
                yield (".")
                s.close()
                time.sleep(1)
        yield ("\n")
        instance.key_file = key_file

        remote_setup(instance, remote_user, key_file)