Пример #1
0
class OkeanosConnector(AbstractConnector):
    """
    Okeanos connector.
    """
    def __init__(self):
        AbstractConnector.__init__(self)
        self.__cyclades = None
        self.__network_client = None
        self.attach_public_ipv4 = False
        self.private_network = -1

    def authenticate(self, authentication=None):
        """

        :param authentication:
        :return:
        """
        if self.__cyclades is not None:
            return True
        try:
            authcl = AstakosClient(authentication['URL'],
                                   authentication['TOKEN'])
            authcl.authenticate()
            self.__cyclades = CycladesClient(
                authcl.get_service_endpoints('compute')['publicURL'],
                authentication['TOKEN'])
            self.__network_client = CycladesNetworkClient(
                authcl.get_service_endpoints('network')['publicURL'],
                authentication['TOKEN'])
        except ClientError:
            stderr.write('Connector initialization failed')
            return False
        return True

    def configure(self, configuration):
        self.authenticate(configuration['auth'])
        if 'private_network' in configuration and configuration[
                'private_network']:
            self.private_network = 0
        if 'attach_public_ipv4' in configuration and configuration[
                'attach_public_ipv4']:
            self.attach_public_ipv4 = True

    def prepare(self):
        """
        In this method, application-level IaaS related actions are executed.
        :return:
        """
        if self.private_network == 0:
            self.private_network = self.create_private_network()

    def create_vm(self, name, flavor_id, image_id):
        """

        :param name:
        :param flavor_id:
        :param image_id:
        :return:
        """
        networks = []
        if self.attach_public_ipv4:
            networks.append({'uuid': self.__create_floating_ip()})
        if self.private_network != -1:
            networks.append({'uuid': self.private_network})

        response = self.__cyclades.create_server(name=name,
                                                 flavor_id=flavor_id,
                                                 image_id=image_id,
                                                 networks=networks)
        ret_value = dict()
        ret_value['password'] = response['adminPass']
        ret_value['id'] = response['id']
        ret_value['user'] = response['metadata']['users']
        ret_value['hostname'] = 'snf-' + str(
            response['id']) + '.vm.okeanos.grnet.gr'
        self.__cyclades.wait_server(server_id=ret_value['id'],
                                    current_status='ACTIVE')
        return ret_value

    def delete_vm(self, server_id):
        """
        Delete VM method. The method is blocking until the VM goes to a "DELETED" state
        :param server_id:
        :return:
        """
        attachments = self.__cyclades.get_server_details(
            server_id)['attachments']
        port_id = None
        for a in attachments:
            if a['OS-EXT-IPS:type'] == 'floating':
                port_id = a['id']
        floating_ip_id = None
        for ip in self.__network_client.list_floatingips():
            if port_id is not None and ip['port_id'] == str(port_id):
                floating_ip_id = ip['id']
        self.__cyclades.delete_server(server_id)
        self.__cyclades.wait_server(
            server_id,
            current_status='DELETED')  # wait until server is deleted
        if floating_ip_id is not None:
            self.__wait_until_ip_released(floating_ip_id)
            self.__network_client.delete_floatingip(floating_ip_id)

    def __wait_until_ip_released(self, floating_ip_id):
        for i in range(1, MAX_WAIT_FOR_LOOPS + 1):
            for ip in self.__network_client.list_floatingips():
                if ip['id'] == floating_ip_id:
                    if ip['instance_id'] is None or ip['instance_id'] == 'None':
                        return True
            sleep(SLEEP_TIMEOUT)

    def list_vms(self):
        """


        :return:
        """
        return self.__cyclades.list_servers()

    def get_status(self, vm_id):
        """

        :param vm_id:
        :return:
        """
        return self.__cyclades.get_server_details(vm_id)

    def get_server_addresses(self,
                             vm_id,
                             ip_version=None,
                             connection_type=None):
        """
        Returns the enabled addresses, as referenced from the IaaS.
        """
        addresses = self.__cyclades.get_server_details(vm_id)['addresses']
        results = []
        while len(addresses) > 0:
            key, value = addresses.popitem()
            if (ip_version is None or value[0]['version'] == ip_version) and \
                    (connection_type is None or value[0]['OS-EXT-IPS:type'] == connection_type):
                results.append(value[0]['addr'])
        return results

    def __create_floating_ip(self):
        self.__network_client.floatingips_get()
        response = self.__network_client.create_floatingip()
        return response['floating_network_id']

    def create_private_network(self):
        """
        Creates a new private network and returns its id
        """
        response = self.__network_client.create_network(
            type='MAC_FILTERED', name='Deployment network')
        self.__network_client.create_subnet(network_id=response['id'],
                                            enable_dhcp=True,
                                            cidr='192.168.0.0/24')
        return response['id']

    def clone(self):
        new_connector = OkeanosConnector()
        new_connector.attach_public_ipv4 = self.attach_public_ipv4
        new_connector.private_network = self.private_network
        new_connector.__network_client = self.__network_client
        new_connector.__cyclades = self.__cyclades
        return new_connector

    def cleanup(self):
        if self.private_network != -1 and self.private_network != 0:
            self.__wait_until_private_net_is_empty(self.private_network)
            self.__network_client.delete_network(self.private_network)

    def __wait_until_private_net_is_empty(self, private_net_id):

        for i in range(1, MAX_WAIT_FOR_LOOPS):
            port_set = set()
            for p in self.__network_client.list_ports():
                port_set.add(p['network_id'])
            if private_net_id not in port_set:
                return
            else:
                sleep(SLEEP_TIMEOUT)

    def serialize(self):
        d = dict()
        d['attach_public_ipv4'] = self.attach_public_ipv4
        d['private_network'] = self.private_network
        return d

    def deserialize(self, state):
        self.attach_public_ipv4 = state['attach_public_ipv4']
        self.private_network = state['private_network']
Пример #2
0
def main():
    """Parse arguments, use kamaki to create cluster, setup using ansible playbooks"""

    (opts, args) = parse_arguments(sys.argv[1:])

    global CYCLADES, TOKEN, my_vnat_network, my_network_client

    AUTHENTICATION_URL = opts.cyclades
    TOKEN = opts.token

    # Cleanup stale servers from previous runs
    if opts.show_stale:
        cleanup_servers(prefix=opts.prefix, delete_stale=opts.delete_stale)
        return 0

    # Initialize a kamaki instance, get endpoints
    user = AstakosClient(AUTHENTICATION_URL, TOKEN)
    my_accountData = user.authenticate()
    endpoints = user.get_endpoints() 
    cyclades_endpoints = user.get_endpoints('compute')
    cyclades_base_url = parseAstakosEndpoints(endpoints, 'cyclades_compute')
    cyclades_network_base_url = parseAstakosEndpoints(endpoints, 'cyclades_network')
    my_cyclades_client = CycladesClient(cyclades_base_url, TOKEN)
    my_compute_client = ComputeClient(cyclades_base_url, TOKEN)
    my_network_client = CycladesNetworkClient(cyclades_network_base_url, TOKEN) 

    my_vnat_network = {}

    # check if 'Hadoop' vnat is created...
    hadoop_vnat_created = False
    my_network_dict = my_network_client.list_networks()
    for n in my_network_dict:
        if n['name'] == 'Hadoop': 
            hadoop_vnat_created = True
            my_vnat_network = n

    # ...else create it
    if hadoop_vnat_created == False:
        log.info("Creating vNAT")
        my_vnat_network = my_network_client.create_network(type='MAC_FILTERED', name='Hadoop');
        my_subnet = my_network_client.create_subnet(network_id=my_vnat_network['id'], cidr='192.168.0.0/24');

    cnt = int(opts.clustersize)	# calculate size of cluster into 'cnt'
    # Initialize
    nodes = []
    masterName = ''

    # Create a file to store the root password for later use
    if not os.path.exists(opts.hadoop_dir+'/bak'):
        os.makedirs(opts.hadoop_dir+'/bak')
    pass_fname = opts.hadoop_dir+'/bak/adminPass'+str(datetime.now())[:19].replace(' ', '')
    adminPass_f = open(pass_fname, 'w')

    initialClusterSize = 0
    server = {}
    if opts.extend == False:
        # Create master node (0th node)
        server = create_machine(opts, my_cyclades_client, 0)
        if server == {}:
            return
    else:
        servers = my_cyclades_client.list_servers(detail=True)
        cluster = [s for s in servers if s["name"].startswith(opts.prefix)]
        initialClusterSize = len(cluster)
        if initialClusterSize==0:
            log.info("Cluster cannot be expanded: it does not exist.")
            return

    servername = "%s-0" % (opts.prefix)
    masterName = servername
    nodes.append(server)

    # Create slave (worker) nodes
    if cnt>1 or opts.extend:
        startingOffset = 1
        if opts.extend: startingOffset = initialClusterSize
        for i in xrange(startingOffset, initialClusterSize+cnt):
            server = {}
            server = create_machine(opts, my_cyclades_client, i)
            if server == {}:
                return;
            nodes.append(server)
            servername = "%s-%d" % (opts.prefix, i)
            # Write the root password to a file
            adminPass_f.write('machine = %s, password = %s\n' % (servername, server['adminPass']))

    adminPass_f.close()

    # Setup Hadoop files and settings on all cluster nodes
    # Create the 'cluster' dictionary out of servers, with only Hadoop-relevant keys (name, ip, integer key)
    servers = my_cyclades_client.list_servers(detail=True)
    cluster = [s for s in my_cyclades_client.list_servers(detail=True) if s["name"].startswith(opts.prefix)]
    cluster0 = [(s["name"], s["attachments"], int(s["name"][s["name"].find('-')+1:])) for s in cluster]
    cluster0 = sorted(cluster0, key=lambda cluster0: cluster0[2])
    cluster = [(cluster0[0][0], cluster0[0][1][2]["ipv4"], cluster0[0][2])]	# master IP, different index 
    cluster2 = [(s[0], s[1][1]['ipv4'], int(s[2])) for s in cluster0[1:]]	# slave IPs
    cluster += cluster2

    # Prepare Ansible-Hadoop config files (hosts, conf/slaves. vnat/etchosts)
    hosts = open(opts.hadoop_dir+'/hosts', 'w')
    hosts.write('[master]\n')
    etchosts = open(opts.hadoop_dir+'/vnat/etchosts', 'w')
    for i in xrange(0, initialClusterSize+cnt):
        for s in cluster:
            if s[0] == opts.prefix+"-"+str(i):
                if s[0] == masterName:
                    hosts.write(s[1]+'\n\n'+'[slaves]\n')
                else:
                    hosts.write(s[1]+'\n')
                etchosts.write(s[1]+'\t'+s[0]+'\n')
    hosts.close()
    etchosts.close()

    slaves = open(opts.hadoop_dir+'/vnat/slaves', 'w')
    for s in cluster[1:]:
        slaves.write(s[0]+'\n')
    slaves.close()

    # Execute respective ansible playbook
    if (opts.extend==False):
        cmd = "ansible-playbook hadoop_vnat.yml -i hosts -vv --extra-vars \""+"is_master=True, master_node="+cluster[0][0]+" master_ip="+cluster[0][1]+"\""+" -l master"
        print cmd
        retval = os.system(cmd)
        cmd = "ansible-playbook hadoop_vnat.yml -i hosts -vv --extra-vars \""+"is_slave=True, master_node="+cluster[0][0]+" master_ip="+cluster[0][1]+"\""+" -l slaves"
        print cmd
        retval = os.system(cmd)
        slave_ip_list = []
        for i in xrange(1, cnt):
            slave_ip_list.append(cluster[i][0])
        enable_ssh_login(cluster[0][1], [cluster[0][0]])
        enable_ssh_login(cluster[0][1], slave_ip_list)
    else:
        hosts_latest = open(opts.hadoop_dir+'/hosts.latest', 'w')
        hosts_latest.write('[master]\n')
        hosts_latest.write(cluster[0][1]+'\n\n'+'[slaves]\n')
        for i in xrange(initialClusterSize, initialClusterSize+cnt):
            hosts_latest.write(cluster[i][1]+'\n')
        hosts_latest.close()
        # update etc/hosts in all nodes - TODO: de-duplicate entries
        cmd = "ansible-playbook hadoop_vnat.yml -i hosts -vv --extra-vars \""+"is_master=True, master_ip="+cluster[0][1]+"\""+" -t etchosts"
        print cmd
        retval = os.system(cmd) 
        cmd = "ansible-playbook hadoop_vnat.yml -i hosts.latest -vv --extra-vars \""+"is_slave=True, master_node="+cluster[0][0]+" master_ip="+cluster[0][1]+"\""+" -l slaves"
        print cmd
        retval = os.system(cmd) 
        slave_ip_list = []
        for i in xrange(initialClusterSize, initialClusterSize+cnt):
            slave_ip_list.append(cluster[i][0])
        print "slave_ip_list=", slave_ip_list 
        enable_ssh_login(cluster[0][1], slave_ip_list)

    # Update conf/slaves in master
    cmd = "ansible-playbook hadoop_vnat.yml -i hosts -vv --extra-vars \""+"is_master=True, master_ip="+cluster[0][1]+"\""+" -l master -t slaves"
    print cmd
    retval = os.system(cmd)

    log.info("Done.")
Пример #3
0
# or implied, of GRNET S.A.

from kamaki.clients.astakos import AstakosClient
from kamaki.clients.cyclades import CycladesNetworkClient

#  Initialize Astakos
AUTHENTICATION_URL = "https://astakos.example.com/identity/v2.0"
TOKEN = "User-Token"
astakos = AstakosClient(AUTHENTICATION_URL, TOKEN)

#  Initialize CycladesComputeClient
service_type = CycladesNetworkClient.service_type
endpoint = astakos.get_endpoint_url(service_type)
network = CycladesNetworkClient(endpoint, TOKEN)

#  Servers
server_1 = "id-for-server-1"
server_2 = "id-for-server-2"

#  Create a new network
type_ = CycladesNetworkClient.types[0]
mynet = network.create_network(type_, name="My Network")

#  Connect servers to network
port_1 = network.create_port(mynet["id"], device_id=server_1)
port_2 = network.create_port(mynet["id"], device_id=server_2)

# Wait until ready
network.wait_port_until(port_1["id"], "ACTIVE")
network.wait_port_until(port_2["id"], "ACTIVE")
Пример #4
0
AUTHENTICATION_URL = "https://astakos.example.com/identity/v2.0"
TOKEN = "User-Token"
astakos = AstakosClient(AUTHENTICATION_URL, TOKEN)

service_type = CycladesComputeClient.service_type
endpoint = astakos.get_endpoint_url(service_type)
compute = CycladesComputeClient(endpoint, TOKEN)

service_type = CycladesNetworkClient.service_type
endpoint = astakos.get_endpoint_url(service_type)
network = CycladesNetworkClient(endpoint, TOKEN)

#  Create VPN and reserve an IP
type_ = CycladesNetworkClient.types[0]
vpn = network.create_network(type_, name="Cluster Network")
unused_ips = filter(lambda ip: not ip["port_id"], network.list_floatingips())
ip = unused_ips[0] if unused_ips else network.create_floatingip()
ip_net = ip["floating_network_id"]

#  Server data
flavor = 420
image = "image-id-for-a-debian-image"

#  Create nodes
networks = [
    dict(uuid=vpn["id"]),
]
node_1 = compute.create_server("Node 1", flavor, image, networks=networks)
node_2 = compute.create_server("Node 2", flavor, image, networks=networks)
Пример #5
0
AUTHENTICATION_URL = "https://astakos.example.com/identity/v2.0"
TOKEN = "User-Token"
astakos = AstakosClient(AUTHENTICATION_URL, TOKEN)

service_type = CycladesComputeClient.service_type
endpoint = astakos.get_endpoint_url(service_type)
compute = CycladesComputeClient(endpoint, TOKEN)

service_type = CycladesNetworkClient.service_type
endpoint = astakos.get_endpoint_url(service_type)
network = CycladesNetworkClient(endpoint, TOKEN)

#  Create VPN and reserve an IP
type_ = CycladesNetworkClient.types[0]
vpn = network.create_network(type_, name="Cluster Network")
unused_ips = filter(lambda ip: not ip["port_id"], network.list_floatingips())
ip = unused_ips[0] if unused_ips else network.create_floatingip()
ip_net = ip["floating_network_id"]

#  Server data
flavor = 420
image = "image-id-for-a-debian-image"

#  Create nodes
networks = [dict(uuid=vpn["id"]), ]
node_1 = compute.create_server("Node 1", flavor, image, networks=networks)
node_2 = compute.create_server("Node 2", flavor, image, networks=networks)

#  Create gateway
networks.append(dict(uuid=ip_net, fixed_ip=ip["floating_ip_address"]))
Пример #6
0
class OkeanosConnector(AbstractConnector):
    """
    Okeanos connector.
    """

    def __init__(self):
        AbstractConnector.__init__(self)
        self.__cyclades = None
        self.__network_client = None
        self.attach_public_ipv4 = False
        self.private_network = -1

    def authenticate(self, authentication=None):
        """

        :param authentication:
        :return:
        """
        if self.__cyclades is not None:
            return True
        try:
            authcl = AstakosClient(authentication['URL'], authentication['TOKEN'])
            authcl.authenticate()
            self.__cyclades = CycladesClient(authcl.get_service_endpoints('compute')['publicURL'],
                                             authentication['TOKEN'])
            self.__network_client = CycladesNetworkClient(authcl.get_service_endpoints('network')['publicURL'],
                                                          authentication['TOKEN'])
        except ClientError:
            stderr.write('Connector initialization failed')
            return False
        return True

    def configure(self, configuration):
        self.authenticate(configuration['auth'])
        if 'private_network' in configuration and configuration['private_network']:
            self.private_network = 0
        if 'attach_public_ipv4' in configuration and configuration['attach_public_ipv4']:
            self.attach_public_ipv4 = True

    def prepare(self):
        """
        In this method, application-level IaaS related actions are executed.
        :return:
        """
        if self.private_network == 0:
            self.private_network = self.create_private_network()

    def create_vm(self, name, flavor_id, image_id):
        """

        :param name:
        :param flavor_id:
        :param image_id:
        :return:
        """
        networks = []
        if self.attach_public_ipv4:
            networks.append({'uuid': self.__create_floating_ip()})
        if self.private_network != -1:
            networks.append({'uuid': self.private_network})

        response = self.__cyclades.create_server(name=name, flavor_id=flavor_id, image_id=image_id, networks=networks)
        ret_value = dict()
        ret_value['password'] = response['adminPass']
        ret_value['id'] = response['id']
        ret_value['user'] = response['metadata']['users']
        ret_value['hostname'] = 'snf-' + str(response['id']) + '.vm.okeanos.grnet.gr'
        self.__cyclades.wait_server(server_id=ret_value['id'], current_status='ACTIVE')
        return ret_value

    def delete_vm(self, server_id):
        """
        Delete VM method. The method is blocking until the VM goes to a "DELETED" state
        :param server_id:
        :return:
        """
        attachments = self.__cyclades.get_server_details(server_id)['attachments']
        port_id = None
        for a in attachments:
            if a['OS-EXT-IPS:type'] == 'floating':
                port_id = a['id']
        floating_ip_id = None
        for ip in self.__network_client.list_floatingips():
            if port_id is not None and ip['port_id'] == str(port_id):
                floating_ip_id = ip['id']
        self.__cyclades.delete_server(server_id)
        self.__cyclades.wait_server(server_id, current_status='DELETED')    # wait until server is deleted
        if floating_ip_id is not None:
            self.__wait_until_ip_released(floating_ip_id)
            self.__network_client.delete_floatingip(floating_ip_id)

    def __wait_until_ip_released(self, floating_ip_id):
        for i in range(1, MAX_WAIT_FOR_LOOPS+1):
            for ip in self.__network_client.list_floatingips():
                if ip['id'] == floating_ip_id:
                    if ip['instance_id'] is None or ip['instance_id'] == 'None':
                        return True
            sleep(SLEEP_TIMEOUT)

    def list_vms(self):
        """


        :return:
        """
        return self.__cyclades.list_servers()

    def get_status(self, vm_id):
        """

        :param vm_id:
        :return:
        """
        return self.__cyclades.get_server_details(vm_id)

    def get_server_addresses(self, vm_id, ip_version=None, connection_type=None):
        """
        Returns the enabled addresses, as referenced from the IaaS.
        """
        addresses = self.__cyclades.get_server_details(vm_id)['addresses']
        results = []
        while len(addresses) > 0:
            key, value = addresses.popitem()
            if (ip_version is None or value[0]['version'] == ip_version) and \
                    (connection_type is None or value[0]['OS-EXT-IPS:type'] == connection_type):
                results.append(value[0]['addr'])
        return results

    def __create_floating_ip(self):
        self.__network_client.floatingips_get()
        response = self.__network_client.create_floatingip()
        return response['floating_network_id']

    def create_private_network(self):
        """
        Creates a new private network and returns its id
        """
        response = self.__network_client.create_network(type='MAC_FILTERED', name='Deployment network')
        self.__network_client.create_subnet(
            network_id=response['id'],
            enable_dhcp=True,
            cidr='192.168.0.0/24'
        )
        return response['id']

    def clone(self):
        new_connector = OkeanosConnector()
        new_connector.attach_public_ipv4 = self.attach_public_ipv4
        new_connector.private_network = self.private_network
        new_connector.__network_client = self.__network_client
        new_connector.__cyclades = self.__cyclades
        return new_connector

    def cleanup(self):
        if self.private_network != -1 and self.private_network != 0:
            self.__wait_until_private_net_is_empty(self.private_network)
            self.__network_client.delete_network(self.private_network)

    def __wait_until_private_net_is_empty(self, private_net_id):

        for i in range(1, MAX_WAIT_FOR_LOOPS):
            port_set = set()
            for p in self.__network_client.list_ports():
                port_set.add(p['network_id'])
            if private_net_id not in port_set:
                return
            else:
                sleep(SLEEP_TIMEOUT)

    def serialize(self):
        d = dict()
        d['attach_public_ipv4'] = self.attach_public_ipv4
        d['private_network'] = self.private_network
        return d

    def deserialize(self, state):
        self.attach_public_ipv4 = state['attach_public_ipv4']
        self.private_network = state['private_network']