Exemplo n.º 1
0
 def sync_aws_key(self, keyname, clobber=False):
     """
     Synchronizes local RSA key with AWS with `keyname`.
     First, Checks whether local RSA priv key exists.
     If it does not exist locally, a new key is created. 
     If it does, but does not match with an
     AWS key, overrides AWS key info.
 
     Arguments:-
         keyname- the name of the key 
         aws_client- the AWS Client object
         clobber- delete existing key on AWS if name collision
     """
     #Check if local SSH key exists; if not create it
     keys.check_and_create_privkey()
     #compare local key with remote key
     if self.check_keyname(keyname):
         #get public key fingerprint
         fingerprint = keys.get_pubkey_fingerprint("aws")
         if not self.check_keyfingerprint(keyname, fingerprint):
             if clobber:
                 #remove key with matching name
                 self.remove_keypair(keyname)
             else:
                 #raise exception
                 exc_msg = "local SSH key does not match key '{}' on AWS server".format(keyname)
                 create_and_raise("SshKeyMismatchException", exc_msg)
     
             #Create key that corresponds with local key
             self.create_keypair(keyname, get_pubkey())
     else:
         self.create_keypair(keyname, get_pubkey())
Exemplo n.º 2
0
    def sync_aws_key(self, keyname, clobber=False):
        """
        Synchronizes local RSA key with AWS with `keyname`.
        First, Checks whether local RSA priv key exists.
        If it does not exist locally, a new key is created. 
        If it does, but does not match with an
        AWS key, overrides AWS key info.
    
        Arguments:-
            keyname- the name of the key 
            aws_client- the AWS Client object
            clobber- delete existing key on AWS if name collision
        """
        #Check if local SSH key exists; if not create it
        keys.check_and_create_privkey()
        #compare local key with remote key
        if self.check_keyname(keyname):
            #get public key fingerprint
            fingerprint = keys.get_pubkey_fingerprint("aws")
            if not self.check_keyfingerprint(keyname, fingerprint):
                if clobber:
                    #remove key with matching name
                    self.remove_keypair(keyname)
                else:
                    #raise exception
                    exc_msg = "local SSH key does not match key '{}' on AWS server".format(
                        keyname)
                    create_and_raise("SshKeyMismatchException", exc_msg)

                #Create key that corresponds with local key
                self.create_keypair(keyname, get_pubkey())
        else:
            self.create_keypair(keyname, get_pubkey())
Exemplo n.º 3
0
def resolve_params(topo_params, user_params):
    """
    Parameters must be passed in the command line
    or be set as environment variables.
    """
    resolved = {}
    #Resolve based on user specified parameters
    if user_params: 
        for pair in user_params.split(" "):
            pname, pvalue = pair.split("=")
            if pname in topo_params:
                resolved[pname] = pvalue
                topo_params.remove(pname)
            else:
                create_and_raise("InvalidParamException", 
                                 "Unknown parameter: '{}' specified.".format(pname))

    #Resolve based on env vars
    for param in topo_params:
        value = os.environ.get(param)
        if not value: 
            create_and_raise("UnspecifiedParameterException",
                             "The parameter {} is undefined".format(param))
        else:
            resolved[param] = value

    return resolved
Exemplo n.º 4
0
 def sync_savi_key(self, keyname, clobber=False):
     """
     Synchronizes local RSA key with SAVI with `keyname`.
     Similar to sync_aws_key.
     Arguments:-
         keyname- the name of the key 
         server_manager- the AWS Client object
         clobber- delete existing key on SAVI if name collision
     """
     #Check if local SSH key exists; if not create it
     keys.check_and_create_privkey()
     
     keypairs = self.get_keypairs()
     for key in keypairs:
         if key["keypair"]["name"] == keyname:
             if key["keypair"]["fingerprint"] == keys.get_pubkey_fingerprint("savi"): 
                 #Nothing to do here
                 return 
             else:
                 if clobber:
                     self.remove_keypair(keyname)
                     self.create_keypair(keyname, keys.get_pubkey())
                 else:
                     exc_msg = "local SSH key does not match key '{}' on SAVI server".format(keyname)
                     create_and_raise("SshKeyException", exc_msg) 
     else:
         self.create_keypair(keyname, keys.get_pubkey())
Exemplo n.º 5
0
def resolve_form(form, params=None, nodes=None, *varargs, **kwargs):
    """
    Resolves deploy-time and parse time forms. This requires
    form names to be unique. 

    Arguments:-
        form: the form to resolve, (string)
        params: the params to the template
        nodes: list of nodes
        args: dict of any unspecified args,
            caller needs to make sure that the method uses the
            appropriate name
    """

    #Check if indeed this object needs to be resolved
    if not needs_resolve(form): return form
    namespace, method, args = get_components(form)

    if namespace == "aws":
        if method == "get_ubuntu_image_id":
            ubuntu_amis = {
                'us-east-1': 'ami-fce3c696',  #N. Virginia
                'us-west-1': 'ami-06116566',  #N. California
                'us-west-2': 'ami-9abea4fb',  #Oregon
            }
            return ubuntu_amis[os.environ["AWS_DEFAULT_REGION"]]

    elif namespace == "utils":
        #Lookup a param
        #TODO: To generalize this, need a way of converting user specified params to python datastructs
        if method == "get_param":
            return params[args[0]]

        elif method == "get_ip":
            return next(node["ip"] for node in nodes
                        if node['name'] == args[0])

        elif method == "get_overlay_ip":
            return next("192.168.{}.{}".format(*node["ip"].split(".")[2:])
                        for node in nodes if node['name'] == args[0])

        #install OVS
        elif method == "install_openvswitch_2_3_3":
            print "In install_openvswitch_2_3_3 ..."
            #NOTE: See if there is a better way
            os.system('scp install_ovs.sh ubuntu@{}:/home/ubuntu'.format(
                node["ip"]))
            os.system("ssh ubuntu@{} '/home/ubuntu/install_ovs.sh'".format(
                node["ip"]))

    create_and_raise(
        "ResolveException",
        "Unable to find either namespace '{}' or method '{}'".format(
            namespace, method))
Exemplo n.º 6
0
def parse_args():
    parser = argparse.ArgumentParser(description='Bootloader command line interface')
    parser.add_argument('-f', '--template-file', nargs=1, help="specify the template to use")
    
    args = parser.parse_args()
    
    if args.template_file:
        bootload(args.template_file)

    else:
        parser.print_help()
        create_and_raise("TemplateNotSpecifiedException", "Please specify a template file")
Exemplo n.º 7
0
def resolve_form(form, params=None, nodes=None, *varargs, **kwargs):
    """
    Resolves deploy-time and parse time forms. This requires
    form names to be unique. 

    Arguments:-
        form: the form to resolve, (string)
        params: the params to the template
        nodes: list of nodes
        args: dict of any unspecified args,
            caller needs to make sure that the method uses the
            appropriate name
    """

    #Check if indeed this object needs to be resolved
    if not needs_resolve(form): return form
    namespace, method, args = get_components(form)

    if namespace == "aws":
        if method == "get_ubuntu_image_id":
            ubuntu_amis = {
                'us-east-1':'ami-fce3c696', #N. Virginia
                'us-west-1':'ami-06116566', #N. California
                'us-west-2':'ami-9abea4fb', #Oregon
            }
            return ubuntu_amis[os.environ["AWS_DEFAULT_REGION"]]
    
    elif namespace == "utils":
        #Lookup a param
        #TODO: To generalize this, need a way of converting user specified params to python datastructs
        if method == "get_param":
            return params[args[0]]

        elif method == "get_ip":
            return next(node["ip"] for node in nodes if node['name'] == args[0])
        
        elif method == "get_overlay_ip":
            return next("192.168.{}.{}".format( *node["ip"].split(".")[2:])
                            for node in nodes if node['name'] == args[0])

        #install OVS
        elif method == "install_openvswitch_2_3_3":
            print "In install_openvswitch_2_3_3 ..."
            #NOTE: See if there is a better way
            os.system('scp install_ovs.sh ubuntu@{}:/home/ubuntu'.format(node["ip"]) )
            os.system("ssh ubuntu@{} '/home/ubuntu/install_ovs.sh'".format(node["ip"]) )

    create_and_raise("ResolveException", 
        "Unable to find either namespace '{}' or method '{}'".format(namespace, method))
Exemplo n.º 8
0
    def create_secgroup(self, name, rules, description=" "):
        """
        Creates a secgroup and adds the rules. If the secgroup 
        exits and the rules don't match, raises and exception.

        rules should be in the format:
        rules = {'ingress': [
                              {'protocol': 'tcp', 'from': 22, 'to':22, 'allowed': ['0.0.0.0/0']  }
                            ], 
                 'egress': []
                 }
        NOTE: nova-network only supports ingress rules; we will ignore any egress rules
        """
        
        resp = self._call_api(service="nova", api="/os-security-groups").json()
        #See if a matching rule exists
        group = next((group for group in resp['security_groups'] if group['name'] == name), None)
        if group:
            if not self._rules_match(rules, group['rules']):
                create_and_raise("SecurityRuleMismatchException", 
                                 "Security group with name {} exists with different rules".format(name))
            else:
                return group["id"]
        else:
            #create group
            data = {"security_group":{"name": name, "description": description}}
            resp = self._call_api(service="nova", api="/os-security-groups", verb="post", data=data).json()
            group_id = resp["security_group"]["id"]

            #Now add the rules
            for rule in rules['ingress']:
                for subrule in self._uncombine_range(rule):
                    data = {
                               "security_group_rule": {
                                   "from_port"      : subrule["from"],
                                   "to_port"        : subrule["to"],
                                   "ip_protocol"    : subrule["protocol"],
                                   "cidr"           : subrule["allowed"], 
                                   "parent_group_id": group_id
                                }
                            }
                            
                    resp = self._call_api(service="nova", api="/os-security-group-rules", verb="post", data=data).json()
Exemplo n.º 9
0
def parse_node(resc, params):
    """
    Parse a node object.
    There are a few special cases to handle
    If optional fields are not specified, then behaviod is undef

    Currently only handles virtual-machines
    """
    #TODO: Error checking; 

    node = {}
    #required fields
    node["image"]  = resolve_form(resc["image"], params=params)
    node["flavor"] = resc["flavor"]
    node["name"]   = resc["name"]
    node["type"]   = resc["type"]

    #Optional Fields
    node["secgroups"] = resc.get("security-groups", [])
    node["key_name"]  = resolve_form(resc.get("key-name"), params=params)
    node["region"]    = resc.get("region", "CORE")
    node["role"]      = resc.get("role") #TODO: should be a list
    
    if resc.get("provider", "savi") == "savi":
        node["provider"]  = "savi" 
        node["tenant"]    = resc["tenant"]
        node["floating_ip"] = resc.get("assign-floating-ip", False)
    else:
        node["provider"] = resc.get("provider")
        if node["provider"] != "aws":
            create_and_raise("InvalidProviderException", "Provider must be 'savi' or 'aws'") 

    #TODO: check whether need to base64 encode, AWS docs say so, but works w/o anyways
    node["user_data"] = resc.get("user-data", '')
   
    node["config"] = resc.get("config", []) 
    
    return node
Exemplo n.º 10
0
    def create_secgroup(self, group_name, rules, description=" "):
        """
        Creates a secgroup and returns its id.
        If a secgroup with the same name exists (group names are unique
        in a VPC), checks whether the rules match. If they don't match
        raises an exception. 

        Rules should be the following format:
        rules = {'ingress': [
                              {'protocol': 'tcp', 'from': 22, 'to':22, 'allowed': ['0.0.0.0/0']  }
                            ], 
                 'egress': []
                 }
        """

        #secgroup names are unique per VPC
        resp = self.ec2_client.describe_security_groups(Filters=[{'Name':'group-name', 'Values': [group_name]}])
        
        if len(resp['SecurityGroups']) > 0:
            #Check if the rules matches
            secgroup = resp['SecurityGroups'][0]

            #Compare ingress and egress rules
            match = self._all_rules_match(rules["ingress"], secgroup["IpPermissions"]) and \
                        self._all_rules_match(rules["egress"], secgroup["IpPermissionsEgress"])
            if match:
                return secgroup['GroupId']
            else:
                create_and_raise("SecurityRuleMismatchException", 
                                 "Security group with name {} exists with different rules".format(group_name))


        else: 
            #create the Secgroup
            vpc_id = self.get_vpc_id()
            resp = self.ec2_client.create_security_group(GroupName=group_name, 
                                                         Description=description,
                                                         VpcId=vpc_id)
            secgroup_id = resp['GroupId']

            #Add the ingress rules
            rules_list = []
            for rule in rules["ingress"]:
                to_add = {"IpProtocol" : rule["protocol"], 
                          "FromPort"   : rule["from"], 
                          "ToPort"     : rule["to"], 
                          "IpRanges"   : [{"CidrIp": rng} for rng in rule["allowed"]]}
                rules_list.append(to_add)

            if rules_list:
                self.ec2_client.authorize_security_group_ingress(GroupId=secgroup_id, IpPermissions=rules_list)
    
            #Add the egress rules
            rules_list = []
            for rule in rules["egress"]:
                to_add = {"IpProtocol" : rule["protocol"], 
                          "FromPort"   : rule["from"], 
                          "ToPort"     : rule["to"], 
                          "IpRanges"   : [{"CidrIp": rng} for rng in rule["allowed"]]}
                rules_list.append(to_add)

            if rules_list:
                #self.ec2_client.authorize_security_group_egress(GroupId=secgroup_id, IpPermissions=rules_list)
                #NOTE: This maybe a boto bug since the docs show the param name is 'IpPermissions', not 'ipPermissions'
                self.ec2_client.authorize_security_group_egress(GroupId=secgroup_id, ipPermissions=rules_list)
Exemplo n.º 11
0
def parse_args():
    """
    Parse arguments and call yaml parser
    """
    #If parser gets too complex, consider: http://chase-seibert.github.io/blog/2014/03/21/python-multilevel-argparse.html
    parser = argparse.ArgumentParser(description='Vino command line interface')
    
    parser.add_argument('-f', '--template-file', nargs=1, help="specify the template to use")
    parser.add_argument('-p', '--parameters', nargs=1, help="parameters to the template")
    parser.add_argument('-c', '--clean-up', action="store_true", help="Deletes any provisioned topologies")
    parser.add_argument('-n', '--nuke-aws', action="store_true", help="Deletes all aws instances")
    parser.add_argument('--nuke-savi', nargs=1, help="Deletes all savi instances matching with the specified prefix")
    parser.add_argument('-d', '--debug', action="store_true", help="Only performs config; requires nodes and edges files to be populated")
    parser.add_argument('--aws-addr-map', action="store_true", help="Prints the address map")


    args = parser.parse_args()

    #Do this since the envvars are required by multiple sub commands.
    #sets the key-value pairs in CONFIG_FILE as envvars
    yaml_to_envvars(CONFIG_FILE)
    config = read_yaml(CONFIG_FILE)

    if args.clean_up:  
        cleanup()

    elif args.nuke_aws:
        nuke_aws()

    elif args.nuke_savi:
        prefix = args.nuke_savi[0]
        nuke_savi(prefix)
        return 

    elif args.template_file:
        #get value of arguments 
        template = args.template_file[0]
        parameters = args.parameters[0] if args.parameters else None
        
        #resolve 
        others, nodes, edges = parse_template(template, parameters)
        #instantiate other declarations
        others = instantiate_others(others)

        #instantiate nodes 
        nodes = instantiate_nodes(nodes)
        
        #create master
        if config["create_master"]:
            #don't modify original nodes array; don't want to call configure_nodes on master node
            mnode = create_master(config)
            nodes.append(mnode)
            write_results(nodes, edges)
        else:
            write_results(nodes, edges)
        
        #Configure the nodes
        configure_nodes(nodes, config)

    elif args.debug:
        #Only runs the configuration scripts
        nodes, edges = read_nodes_edges()
        #Configure the nodes
        configure_nodes(nodes, config)

    elif args.aws_addr_map:
       aws_addr_map() 

    else:
        parser.print_help()
        create_and_raise("TemplateNotSpecifiedException", "Please specify a template file")
Exemplo n.º 12
0
    def create_secgroup(self, group_name, rules, description=" "):
        """
        Creates a secgroup and returns its id.
        If a secgroup with the same name exists (group names are unique
        in a VPC), checks whether the rules match. If they don't match
        raises an exception. 

        Rules should be the following format:
        rules = {'ingress': [
                              {'protocol': 'tcp', 'from': 22, 'to':22, 'allowed': ['0.0.0.0/0']  }
                            ], 
                 'egress': []
                 }
        """

        #secgroup names are unique per VPC
        resp = self.ec2_client.describe_security_groups(
            Filters=[{
                'Name': 'group-name',
                'Values': [group_name]
            }])

        if len(resp['SecurityGroups']) > 0:
            #Check if the rules matches
            secgroup = resp['SecurityGroups'][0]

            #Compare ingress and egress rules
            match = self._all_rules_match(rules["ingress"], secgroup["IpPermissions"]) and \
                        self._all_rules_match(rules["egress"], secgroup["IpPermissionsEgress"])
            if match:
                return secgroup['GroupId']
            else:
                create_and_raise(
                    "SecurityRuleMismatchException",
                    "Security group with name {} exists with different rules".
                    format(group_name))

        else:
            #create the Secgroup
            vpc_id = self.get_vpc_id()
            resp = self.ec2_client.create_security_group(
                GroupName=group_name, Description=description, VpcId=vpc_id)
            secgroup_id = resp['GroupId']

            #Add the ingress rules
            rules_list = []
            for rule in rules["ingress"]:
                to_add = {
                    "IpProtocol": rule["protocol"],
                    "FromPort": rule["from"],
                    "ToPort": rule["to"],
                    "IpRanges": [{
                        "CidrIp": rng
                    } for rng in rule["allowed"]]
                }
                rules_list.append(to_add)

            if rules_list:
                self.ec2_client.authorize_security_group_ingress(
                    GroupId=secgroup_id, IpPermissions=rules_list)

            #Add the egress rules
            rules_list = []
            for rule in rules["egress"]:
                to_add = {
                    "IpProtocol": rule["protocol"],
                    "FromPort": rule["from"],
                    "ToPort": rule["to"],
                    "IpRanges": [{
                        "CidrIp": rng
                    } for rng in rule["allowed"]]
                }
                rules_list.append(to_add)

            if rules_list:
                #self.ec2_client.authorize_security_group_egress(GroupId=secgroup_id, IpPermissions=rules_list)
                #NOTE: This maybe a boto bug since the docs show the param name is 'IpPermissions', not 'ipPermissions'
                self.ec2_client.authorize_security_group_egress(
                    GroupId=secgroup_id, ipPermissions=rules_list)