De Cero a Héroe con la API de IaaS OpenStack de K5 (Python 2.7X)

2017-01-27

De Cero a Héroe con la API de IaaS OpenStack de K5 (Python 2.7X)

Machine-translated from English. Read the English original

Hoy repasaré todos los pasos necesarios para desplegar un servidor en la plataforma IaaS de Fujitsu K5 utilizando únicamente llamadas a la API basadas en OpenStack. He elegido Python 2.7X con fines de demostración, ya que es en lo que se basa principalmente OpenStack. Sin embargo, debería ser bastante fácil portar las llamadas a la API a otro lenguaje de scripting, ya que no estoy utilizando ninguna biblioteca intermedia; todas mis solicitudes http hablan directamente con los puntos de conexión de K5.

Requisitos previos para este tutorial:

Pasos necesarios para construir un servidor utilizando la API de OpenStack

Una vez que hayas satisfecho los requisitos previos anteriores, repasemos rápidamente lo que se necesita para construir un servidor en un proyecto dentro de OpenStack.

k5-iaas-server-build-via-api-1

Para el resto de este tutorial, pasaré revista a cada llamada a la API detallando qué se envía y qué se devuelve.

sbstep1

Paso 1 – Obtener un token K5 válido vinculado al proyecto donde deseas desplegar el servidor. Aquí es donde necesitarás tus credenciales de inicio de sesión de K5/OpenStack. Estas se proporcionarán con la solicitud inicial de un token vinculado al proyecto de la siguiente manera:

def get_scoped_token(adminUser, adminPassword, contract, projectid, region):

    identityURL = 'https://identity.' + region + \
        '.cloud.global.fujitsu.com/v3/auth/tokens'

    try:
        response = requests.post(identityURL,
                                 headers={'Content-Type': 'application/json',
                                          'Accept': 'application/json'},
                                 json={"auth":
                                         {"identity":
                                          {"methods": ["password"], "password":
                                           {"user":
                                           {"domain":
                                               {"name": contract},
                                            "name": adminUser,
                                            "password": adminPassword
                                            }}},
                                          "scope":
                                          {"project":
                                           {"id": projectid
                                            }}}})

        return response
    except:
        return 'Regional Project Token Scoping Failure'

def main():

  k5token = get_scoped_token(adminUser, adminPassword, contract, demoProjectAid, region).json()
  # print the output for demonstartion purposes
  pprint.pprint(k5token)

Si se han proporcionado credenciales válidas, obtendrás un objeto de respuesta JSON que contiene los puntos de conexión de K5 registrados en su catálogo de keystone de OpenStack de la siguiente manera:

{u'token': {u'catalog': [{u'endpoints': [{u'id': u'b506af0e016a4b5fb592f196da569a41',
                                          u'interface': u'public',
                                          u'name': u'objectstorage',
                                          u'region': u'uk-1',
                                          u'url': u'https://objectstorage.uk-1.cloud.global.fujitsu.com/v1/AUTH_7015d1478a4c4bd7b970215d7b0260dd'}],
                          u'id': u'024329e4fde148e58ecd90b7d9872438',
                          u'type': u'object-store'},
                         {u'endpoints': [{u'id': u'0419c448001845af8f6828cf49745e72',
                                          u'interface': u'public',
                                          u'name': u'keymanagement',
                                          u'region': u'uk-1',
                                          u'url': u'https://keymanagement.uk-1.cloud.global.fujitsu.com/v1'}],
                          u'id': u'07f309b0ef9d42758ea4de47bdca9c32',
                          u'type': u'keystore'},
                         {u'endpoints': [{u'id': u'e1cc93936fb94cdbadc20f17c4ad3140',
                                          u'interface': u'public',
                                          u'name': u'certificate',
                                          u'region': u'uk-1',
                                          u'url': u'https://certificate.uk-1.cloud.global.fujitsu.com/v1'}],
                          u'id': u'0bd9a971e97d4c15af6b94311e4e9c15',
                          u'type': u'certificate'},
                         {u'endpoints': [{u'id': u'c3ee708a6ae24ddf92c078526c36a446',
                                          u'interface': u'public',
                                          u'name': u'orchestration',
                                          u'region': u'uk-1',
                                          u'url': u'https://orchestration.uk-1.cloud.global.fujitsu.com/v1/7015d1478a4c4bd7b970215d7b0260dd'}],
                          u'id': u'0dafa2a9240c41268c37818979769c88',
                          u'type': u'orchestration'},
                         {u'endpoints': [{u'id': u'ba9061d324954b1a9f6b1c1f5d4a5c5e',
                                          u'interface': u'public',
                                          u'name': u'blockstorage',
                                          u'region': u'uk-1',
                                          u'url': u'https://blockstorage.uk-1.cloud.global.fujitsu.com/v1/7015d1478a4c4bd7b970215d7b0260dd'}],
                          u'id': u'0ec640e57e4d4374841d2ab7b292f2c2',
                          u'type': u'volume'},
                         {u'endpoints': [{u'id': u'169bcb3f92384f709232864f4d5304eb',
                                          u'interface': u'public',
                                          u'name': u'loadbalancing',
                                          u'region': u'uk-1',
                                          u'url': u'https://loadbalancing.uk-1.cloud.global.fujitsu.com'}],
                          u'id': u'15ef761fa00a438985213aec7b6fb18a',
                          u'type': u'loadbalancing'},
                         {u'endpoints': [],
                          u'id': u'1a53a2e82370422d90174c4acf585ea9',
                          u'type': u'dwh'},
                         {u'endpoints': [],
                          u'id': u'1b35fa74ae0e46ebbc2014f976fec0e1',
                          u'type': u'contract'},
                         {u'endpoints': [],
                          u'id': u'253096ed430c49c48c9f3549e867b538',
                          u'type': u'appplatform'},
                         {u'endpoints': [{u'id': u'e26ad89a682d4c8f8a71c9e76cd785b4',
                                          u'interface': u'public',
                                          u'name': u'compute-w',
                                          u'region': u'uk-1',
                                          u'url': u'https://compute-w.uk-1.cloud.global.fujitsu.com'}],
                          u'id': u'327c11710f184555b43bc6fdfc47626b',
                          u'type': u'compute-w'},
                         {u'endpoints': [],
                          u'id': u'3435ad7a1da04b1cb2e249665529eb51',
                          u'type': u'notification'},
                         {u'endpoints': [{u'id': u'f70e51b9a6a74a87a4c7055b8df8bedf',
                                          u'interface': u'public',
                                          u'name': u'compute',
                                          u'region': u'uk-1',
                                          u'url': u'https://compute.uk-1.cloud.global.fujitsu.com/v2/7015d1478a4c4bd7b970215d7b0260dd'}],
                          u'id': u'3e19093f50cc4590973c8953e2c327f9',
                          u'type': u'compute'},
                         {u'endpoints': [{u'id': u'c46b5ec51ab04402a9ffd8177743ba6f',
                                          u'interface': u'public',
                                          u'name': u'queue',
                                          u'region': u'uk-1',
                                          u'url': u'https://queue.uk-1.cloud.global.fujitsu.com'}],
                          u'id': u'4a9ab69b74ec4948a0a6958177d30387',
                          u'type': u'queue'},
                         {u'endpoints': [{u'id': u'071ee50be4b341558e37f84abac47d02',
                                          u'interface': u'public',
                                          u'name': u'autoscale',
                                          u'region': u'uk-1',
                                          u'url': u'https://autoscale.uk-1.cloud.global.fujitsu.com/autoscale_schedulers'}],
                          u'id': u'4f158b2836434c7ca6ee47e40a3ee56c',
                          u'type': u'autoscale'},
                         {u'endpoints': [{u'id': u'6ac15657fbc548d7ab2ed986b8d94192',
                                          u'interface': u'public',
                                          u'name': u'telemetry',
                                          u'region': u'uk-1',
                                          u'url': u'https://telemetry.uk-1.cloud.global.fujitsu.com'}],
                          u'id': u'54ee7596f0e1433cb8db6201be2cf772',
                          u'type': u'metering'},
                         {u'endpoints': [],
                          u'id': u'5954129d136e4a76b7cd6f3d1f3808b5',
                          u'type': u'cdn'},
                         {u'endpoints': [],
                          u'id': u'5a252878ffd7402498b6b74b575a899a',
                          u'type': u'oss'},
                         {u'endpoints': [{u'id': u'2d600a5de6ec42c6a5eab7b519832d87',
                                          u'interface': u'public',
                                          u'name': u'rolemanagement',
                                          u'region': u'uk-1',
                                          u'url': u'https://rolemanagement.uk-1.cloud.global.fujitsu.com/v1'}],
                          u'id': u'5bc90099f0ad490c811239a6a3a8f853',
                          u'type': u'rolemanagement'},
                         {u'endpoints': [{u'id': u'768450282d5546409395d2cb35502dad',
                                          u'interface': u'public',
                                          u'name': u'compute-b',
                                          u'region': u'uk-1',
                                          u'url': u'https://compute-b.uk-1.cloud.global.fujitsu.com'}],
                          u'id': u'65f754202b6049578e9a292a801e28f7',
                          u'type': u'compute-b'},
                         {u'endpoints': [{u'id': u'675910513a7e466c84c39c5ca9445b81',
                                          u'interface': u'public',
                                          u'name': u'networking',
                                          u'region': u'uk-1',
                                          u'url': u'https://networking.uk-1.cloud.global.fujitsu.com'}],
                          u'id': u'6cf37e33dc7140b9b032faabfa53a53e',
                          u'type': u'network'},
                         {u'endpoints': [],
                          u'id': u'7426c97af5174c1abdb8b84ba02227ce',
                          u'type': u'dns'},
                         {u'endpoints': [{u'id': u'6976cbeed14c464da15c13e949b41607',
                                          u'interface': u'public',
                                          u'name': u'database',
                                          u'region': u'uk-1',
                                          u'url': u'https://database.uk-1.cloud.global.fujitsu.com/v1.0/7015d1478a4c4bd7b970215d7b0260dd'}],
                          u'id': u'75c0280f15844d7a9eb22b1ad5a978e8',
                          u'type': u'database'},
                         {u'endpoints': [{u'id': u'db15a7126d4a4f1f81903bb4d56be32b',
                                          u'interface': u'admin',
                                          u'name': u'identity',
                                          u'region': u'uk-1',
                                          u'url': u'https://identity.uk-1.cloud.global.fujitsu.com/v2.0'}],
                          u'id': u'79066fe949064550930a61b33a49eb53',
                          u'type': u'identity'},
                         {u'endpoints': [],
                          u'id': u'804190a423804019aab8fd934db0086e',
                          u'type': u'intdns'},
                         {u'endpoints': [],
                          u'id': u'8d364df08cbc4d7188f0cf83744b0336',
                          u'type': u'invoicing'},
                         {u'endpoints': [],
                          u'id': u'9674ae5917af401397071c028ff33b68',
                          u'type': u'catalog'},
                         {u'endpoints': [{u'id': u'fd6g35fgknrzumut7bx6p6bwzehkfhrz',
                                          u'interface': u'public',
                                          u'name': u'software',
                                          u'region': u'uk-1',
                                          u'url': u'https://software.uk-1.cloud.global.fujitsu.com/v1.0'}],
                          u'id': u'9760973e49b04b00b41e60c180a80562',
                          u'type': u'software'},
                         {u'endpoints': [{u'id': u'8c4ace3bbbd44883b5762a9ad8432a46',
                                          u'interface': u'public',
                                          u'name': u'blockstoragev2',
                                          u'region': u'uk-1',
                                          u'url': u'https://blockstorage.uk-1.cloud.global.fujitsu.com/v2/7015d1478a4c4bd7b970215d7b0260dd'}],
                          u'id': u'9bf82d0466714eee86e304ab3301aec9',
                          u'type': u'volumev2'},
                         {u'endpoints': [],
                          u'id': u'a2b90094346c48deabb9ca645bacf588',
                          u'type': u'dnsadmin'},
                         {u'endpoints': [{u'id': u'225257ec50ef47668185587cc6edb95d',
                                          u'interface': u'public',
                                          u'name': u'vmimport',
                                          u'region': u'uk-1',
                                          u'url': u'https://vmimport.uk-1.cloud.global.fujitsu.com'}],
                          u'id': u'c73fa07c3b604b4f89d5a2b9c4621cf2',
                          u'type': u'vmimport'},
                         {u'endpoints': [{u'id': u'27dc2bba1c5d4a14b68657fc8fdd4e3e',
                                          u'interface': u'public',
                                          u'name': u'identityv3',
                                          u'region': u'uk-1',
                                          u'url': u'https://identity.uk-1.cloud.global.fujitsu.com/v3'}],
                          u'id': u'cc6f50d496884ef0a751acb2e1eceedd',
                          u'type': u'identityv3'},
                         {u'endpoints': [{u'id': u'06fbcf8235434f23a08faed03b4af9ac',
                                          u'interface': u'public',
                                          u'name': u'appmanagement',
                                          u'region': u'uk-1',
                                          u'url': u'https://applicationmanagement.uk-1.cloud.global.fujitsu.com'}],
                          u'id': u'ce2f6bbe7a9f446b82d63725bd7bb484',
                          u'type': u'appmanagement'},
                         {u'endpoints': [],
                          u'id': u'd07aa581c0734b6bb85cd496115b5110',
                          u'type': u'nosql'},
                         {u'endpoints': [],
                          u'id': u'd2f57dcae4c84466ac357220ff3d8900',
                          u'type': u'baremetal'},
                         {u'endpoints': [],
                          u'id': u'd4601f51af8f43f3b0e3409e4cbac690',
                          u'type': u'mail'},
                         {u'endpoints': [{u'id': u'bf356065e45349a5bde5e043c95a1923',
                                          u'interface': u'public',
                                          u'name': u'networking-ex',
                                          u'region': u'uk-1',
                                          u'url': u'https://networking-ex.uk-1.cloud.global.fujitsu.com'}],
                          u'id': u'd4937aa1275c41378bf2ae1dbe829c68',
                          u'type': u'networking-ex'},
                         {u'endpoints': [{u'id': u'dc2ebf9d6fc04f1facc263a733cf754d',
                                          u'interface': u'public',
                                          u'name': u'global-identity',
                                          u'region': u'jp-east-1',
                                          u'url': u'https://identity.gls.cloud.global.fujitsu.com/v3'}],
                          u'id': u'e74b9c29d6504f10a8fb8e1495f3f5c6',
                          u'type': u'global-identity'},
                         {u'endpoints': [{u'id': u'a832d640886b4ef89027339a2edf8fcd',
                                          u'interface': u'public',
                                          u'name': u'image',
                                          u'region': u'uk-1',
                                          u'url': u'https://image.uk-1.cloud.global.fujitsu.com'}],
                          u'id': u'ea850dab0e964e12a9f66787ee8623ae',
                          u'type': u'image'},
                         {u'endpoints': [],
                          u'id': u'f1302a2477bf492bb3e867952175974a',
                          u'type': u'billing'},
                         {u'endpoints': [{u'id': u'e8bde8fe61a14a88b414e5568fc17201',
                                          u'interface': u'public',
                                          u'name': u'import-export',
                                          u'region': u'uk-1',
                                          u'url': u'https://import-export.uk-1.cloud.global.fujitsu.com'}],
                          u'id': u'fc302725919645199373077fa299fc6e',
                          u'type': u'import-export'}],
            u'expires_at': u'2017-01-27T13:53:55.982381Z',
            u'extras': {},
            u'issued_at': u'2017-01-27T10:53:55.982425Z',
            u'methods': [u'password'],
            u'project': {u'domain': {u'id': u'3256d41b17014d5c99727993d6fca821',
                                     u'name': u'YssmW1yI'},
                         u'id': u'7015d1478a4c4bd7b970215d7b0260dd',
                         u'name': u'Project_A'},
            u'roles': [{u'id': u'0739580a550d4a0f9c78f45a9f038c05',
                        u'name': u'cpf_systemowner'},
                       {u'id': u'3af119c426a742999e7890f6d1f70b36',
                        u'name': u'cpf_admin'}],
            u'user': {u'domain': {u'id': u'3256d41b17014d5c99727993d6fca821',
                                  u'name': u'YssmW1yI'},
                      u'id': u'03758af9df694db784c3547ab8217abb',
                      u'name': u'landg'}}}

Esta información es muy importante, ya que cuando desees automatizar completamente K5, así es como detectas tus varios puntos de conexión para los servicios que necesitas consumir.

Nota: Los puntos de conexión que tienen un sufijo '-ex' en sus nombres son los puntos de conexión mejorados de OpenStack. Estos puntos de conexión incluyen las características adicionales que Fujitsu ha añadido a K5 por encima y más allá de las características estándar de OpenStack.

Entonces, ¿qué falta en esta imagen...? ¿Dónde está el token??? No temas, en realidad se almacena en la cabecera de la respuesta en una variable llamada 'X-Subject-Token'. Por ejemplo –

  # print the K5 poject scoped token
  print "\n\n K5 Project Scoped Token :", k5token.headers['X-Subject-Token'], "\n"

...revela un token, que por cierto es válido durante 2 horas, de la siguiente manera..

K5 Project Scoped Token : f5b72cd06517447fae59360f6deba7d8

Este token debe pasarse con todas las llamadas posteriores a la API de K5 en la cabecera para proporcionar tus credenciales de autenticación y autorización a cada solicitud de servicio.

El punto de conexión de la API de OpenStack neutron estándar se puede extraer de la respuesta anterior buscando el punto de conexión llamado 'networking'. He utilizado la siguiente función para devolver la URL del punto de conexión que estoy buscando –

def get_endpoint(k5token, endpoint_type):
    # list the endpoints
    for ep in k5token.json()['token']['catalog']:
        if len(ep['endpoints'])>0:
            # if this is the endpoint that  I'm looking for return the url
            if endpoint_type == ep['endpoints'][0].get('name'):
                #pprint.pprint(ep)
                return ep['endpoints'][0].get('url')

Por ejemplo –

  # list the networking endpoints
    print get_endpoint(k5token,"networking")

Devolverá el punto de conexión de la API de neutron que necesito –

 K5 Networking EndPoints :
https://networking.uk-1.cloud.global.fujitsu.com

Ahora que tenemos los detalles necesarios del token y del punto de conexión, pasemos a la siguiente etapa.

sbstep2

Paso 2 – Crear la red de capa 2. La siguiente llamada de neutron crea una subred de capa 2 de K5 con las propiedades que pasas a través de la API de la siguiente manera:

def create_network(k5token, name, availability_zone):

    networkURL = unicode(get_endpoint(k5token, "networking")) + unicode('/v2.0/networks')
    print networkURL
    token = k5token.headers['X-Subject-Token']
    try:
        response = requests.post(networkURL,
                                 headers={'X-Auth-Token': token,
                                         'Content-Type': 'application/json'},
                                 json={
                                            "network":
                                            {
                                              "name": name,
                                              "admin_state_up": True,
                                              "availability_zone": availability_zone
                                             }
                                        })
        return response
    except:
        return ("\nUnexpected error:", sys.exc_info())

Por ejemplo –

    # Create a layer 2 virtual network
    network = create_network(k5token, "demonet", "uk-1b")
    print network
    print network.json()

produce –

https://networking.uk-1.cloud.global.fujitsu.com/v2.0/networks

{u'network': {u'status': u'ACTIVE', u'subnets': [], u'name': u'demonet', u'admin_state_up': True, u'tenant_id': u'7015d1478a4c4bd7b970215d7b0260dd', u'availability_zone': u'uk-1b', u'shared': False, u'id': u'02fd7be4-b5f1-455c-8aea-37b299e85ddd'}}

Necesitamos capturar el id de la red recién creada, ya que lo utilizaremos en la siguiente llamada a la API –

    network_id = network.json()['network'].get('id')

Ahora creemos nuestra subred.

sbstep3

Paso 3 – Crear la subred de capa 3. Una vez más, estamos utilizando la llamada a la API de neutron estándar aquí y pasando el id de la red recién creada a la llamada. La función utilizada se ve así –

def create_subnet(k5token, name, netid, cidr, az):

    networkURL = unicode(get_endpoint(k5token, "networking")) + unicode('/v2.0/subnets')
    print networkURL
    token = k5token.headers['X-Subject-Token']
    try:

        response = requests.post(networkURL,
                                headers={'X-Auth-Token': token,
                                         'Content-Type': 'application/json'},
                                json={
                                             "subnet": {
                                                 "name": name,
                                                 "network_id": netid,
                                                 "ip_version": 4,
                                                 "cidr": cidr,
                                                 "availability_zone": az
                                             }
                                            })
        return response
    except:
        return ("\nUnexpected error:", sys.exc_info())

Y cuando se invoca de la siguiente manera –

    subnet = create_subnet(k5token, "demosubnet", network_id, "192.168.10.0/24", "uk-1b")

    print subnet

    print subnet.json()

    subnet_id = subnet.json()['subnet'].get('id')

    print subnet_id

produce la siguiente respuesta –

https://networking.uk-1.cloud.global.fujitsu.com/v2.0/subnets

{u'subnet': {u'name': u'demosubnet', u'enable_dhcp': True, u'availability_zone': u'uk-1b', u'network_id': u'1af9e3fe-4546-4b59-a5a5-10e48af5302a', u'tenant_id': u'7015d1478a4c4bd7b970215d7b0260dd', u'dns_nameservers': [], u'allocation_pools': [{u'start': u'192.168.10.2', u'end': u'192.168.10.254'}], u'host_routes': [], u'ip_version': 4, u'gateway_ip': u'192.168.10.1', u'cidr': u'192.168.10.0/24', u'id': u'2322908f-cf58-4124-a273-86a33cc429b5'}}
2322908f-cf58-4124-a273-86a33cc429b5

Observa que ahora también hemos capturado el id de la nueva subred. Esperemos que el patrón se vuelva obvio ahora a medida que avanzamos al siguiente paso.

sbstep4

Paso 4 – Crear un enrutador virtual. Una vez más, estamos trabajando con el punto de conexión de neutrons de OpenStack esta vez construyendo un enrutador virtual. Se ha utilizado la siguiente función –

def create_router(k5token, name, availability_zone):

    networkURL = unicode(get_endpoint(k5token, "networking")) + unicode('/v2.0/routers')
    print networkURL
    token = k5token.headers['X-Subject-Token']

    try:
        response = requests.post(networkURL,
                                headers={'X-Auth-Token': token,
                                         'Content-Type': 'application/json'},
                                json={
                                          "router": {
                                               "name": name,
                                               "admin_state_up": True,
                                               "availability_zone": availability_zone
                                          }})
        return response
    except:
        return ("\nUnexpected error:", sys.exc_info())

que, cuando se invoca así –

    # Create a layer 3 virtual router
    router = create_router(k5token, "demorouter", "uk-1b")

    print router

    print router.json()

    router_id = router.json()['router'].get('id')

    print router_id

devuelve –

https://networking.uk-1.cloud.global.fujitsu.com/v2.0/routers

{u'router': {u'status': u'ACTIVE', u'external_gateway_info': None, u'name': u'demorouter', u'admin_state_up': True, u'tenant_id': u'7015d1478a4c4bd7b970215d7b0260dd', u'availability_zone': u'uk-1b', u'id': u'0a0661a9-7e30-4f8e-904a-c4a9469d3fca'}}
0a0661a9-7e30-4f8e-904a-c4a9469d3fca

Una vez más, capturamos el identificador del recurso recién creado – router_id.

sbstep5

Paso 5 – Ahora configuremos el enrutador. Primero establecemos la puerta de enlace externa utilizando la siguiente llamada a la función –

def update_router_gateway(k5token, router_id, network_id):

    networkURL = unicode(get_endpoint(k5token, "networking")) + unicode('/v2.0/routers/') + router_id
    print networkURL
    token = k5token.headers['X-Subject-Token']

    try:
        response = requests.put(networkURL,
                                headers={'X-Auth-Token': token,
                                         'Content-Type': 'application/json'},
                                json={
                                         "router": {
                                                     "external_gateway_info": {
                                                                                    "network_id": network_id
                                                     }
                                         }})
        return response
    except:
        return ("\nUnexpected error:", sys.exc_info())

llamada desde el cuerpo del script de la siguiente manera –

    # Add external gateway to router (extaz2 is the external network id for the external network in availability zone b)
    router_gateway = update_router_gateway(k5token, router_id, extaz2)

    print router_gateway

    print router_gateway.json()

produciendo los siguientes resultados –

https://networking.uk-1.cloud.global.fujitsu.com/v2.0/routers/245a02e7-8b0e-4d1f-af6a-dfc07ed916e0

{u'router': {u'status': u'ACTIVE', u'external_gateway_info': {u'network_id': u'd730db50-0e0c-4790-9972-1f6e2b8c4915', u'enable_snat': True}, u'name': u'demorouter', u'admin_state_up': True, u'tenant_id': u'7015d1478a4c4bd7b970215d7b0260dd', u'availability_zone': u'uk-1b', u'routes': [], u'id': u'245a02e7-8b0e-4d1f-af6a-dfc07ed916e0'}}

sbstep6

Paso 6 – Ahora 'conectaremos' nuestra red virtual a nuestro enrutador virtual con esta llamada a la función –

def add_interface_to_router(k5token, router_id, subnet_id):

    networkURL = unicode(get_endpoint(k5token, "networking")) + unicode('/v2.0/routers/') + router_id + '/add_router_interface'
    print networkURL
    token = k5token.headers['X-Subject-Token']

    try:
        response = requests.put(networkURL,
                                headers={'X-Auth-Token': token,
                                         'Content-Type': 'application/json'},
                                json={
                                    "subnet_id": subnet_id})
        return response
    except:
        return ("\nUnexpected error:", sys.exc_info())

que se invoca de esta manera –

    # Plug new network subnet into the router
    router_interface = add_interface_to_router(k5token, router_id, subnet_id)

    print router_interface

    print router_interface.json()

con la siguiente salida –

https://networking.uk-1.cloud.global.fujitsu.com/v2.0/routers/43e95138-9124-4e04-a5d4-ae5b90f4fded/add_router_interface

{u'subnet_id': u'16b59543-c303-4e33-9b96-b538625f40b2', u'tenant_id': u'7015d1478a4c4bd7b970215d7b0260dd', u'port_id': u'1ba71079-288e-49b7-925d-fb31658bc9c6', u'id': u'43e95138-9124-4e04-a5d4-ae5b90f4fded', u'availability_zone': u'uk-1b'}

Esto completa los conceptos básicos de la infraestructura de red.

sbstep7

Paso 7 – El servidor necesitará un grupo de seguridad asignado a sus interfaces de red, así que crearemos esto ahora junto con las reglas que permitirán los protocolos ssh, tcp y rdp solo entrantes.

Se utilizó esta llamada a la API para crear el grupo de seguridad –

def create_security_group(k5token, name, description):

    networkURL = unicode(get_endpoint(k5token, "networking")) + unicode('/v2.0/security-groups')
    print networkURL
    token = k5token.headers['X-Subject-Token']

    try:
        response = requests.post(networkURL,
                                headers={'X-Auth-Token': token, 'Content-Type': 'application/json', 'Accept': 'application/json'},
                                json={
                                        "security_group": {
                                            "name": name,
                                            "description": description
                                            }
                                        })
        return response
    except:
        return ("\nUnexpected error:", sys.exc_info())

que se invoca de la siguiente manera –

    # Create a new security group
    security_group = create_security_group(k5token, "demosecuritygroup", "Demo Security Group Allows RDP, SSH and ICMP")

    print security_group

    print security_group.json()

    security_group_id = security_group.json()['security_group'].get('id')

    print security_group_id

resultando en esta salida –

https://networking.uk-1.cloud.global.fujitsu.com/v2.0/security-groups

{u'security_group': {u'id': u'ae44389e-f884-4726-8bc3-ec3cbc7b876e', u'tenant_id': u'7015d1478a4c4bd7b970215d7b0260dd', u'description': u'Demo Security Group Allows RDP, SSH and ICMP', u'security_group_rules': [{u'remote_group_id': None, u'direction': u'egress', u'protocol': None, u'ethertype': u'IPv6', u'port_range_max': None, u'security_group_id': u'ae44389e-f884-4726-8bc3-ec3cbc7b876e', u'tenant_id': u'7015d1478a4c4bd7b970215d7b0260dd', u'port_range_min': None, u'remote_ip_prefix': None, u'id': u'55d5c3f1-3cf0-46c0-b876-6e89a1a1fc55'}, {u'remote_group_id': None, u'direction': u'egress', u'protocol': None, u'ethertype': u'IPv4', u'port_range_max': None, u'security_group_id': u'ae44389e-f884-4726-8bc3-ec3cbc7b876e', u'tenant_id': u'7015d1478a4c4bd7b970215d7b0260dd', u'port_range_min': None, u'remote_ip_prefix': None, u'id': u'c83371a8-f217-4038-982a-0165df8e9f4f'}], u'name': u'demosecuritygroup'}}
ae44389e-f884-4726-8bc3-ec3cbc7b876e

sbstep8

Paso 8 – Crear nuestras reglas de grupo de seguridad con la siguiente llamada a la API –

def create_security_group_rule(k5token, security_group_id, direction, portmin, portmax, protocol):

    networkURL = unicode(get_endpoint(k5token, "networking")) + unicode('/v2.0/security-group-rules')
    print networkURL
    token = k5token.headers['X-Subject-Token']

    try:
        response = requests.post(networkURL,
                                headers={'X-Auth-Token': token, 'Content-Type': 'application/json', 'Accept': 'application/json'},
                                json={
                                        "security_group_rule": {
                                            "direction": direction,
                                            "port_range_min": portmin,
                                            "ethertype": "IPv4",
                                            "port_range_max": portmax,
                                            "protocol": protocol,
                                            "security_group_id": security_group_id
                                            }
                                        })
        return response
    except:
        return ("\nUnexpected error:", sys.exc_info())

de nuevo (sé que es repetitivo) la llamada se invoca de la siguiente manera –

    # Create security group rules
    # allow rdp
    rdp_rule = create_security_group_rule(k5token, security_group_id, "ingress", "3389", "3389", "tcp")

    print rdp_rule

    print rdp_rule.json()

    # allow ssh # allow rdp
    ssh_rule = create_security_group_rule(k5token, security_group_id, "ingress", "22", "22", "tcp")

    print ssh_rule

    print ssh_rule.json()

     # allow icmp
    icmp_rule = create_security_group_rule(k5token, security_group_id, "ingress", "0", "0", "icmp")

    print icmp_rule

    print icmp_rule.json()

produciendo –

https://networking.uk-1.cloud.global.fujitsu.com/v2.0/security-group-rules

{u'security_group_rule': {u'remote_group_id': None, u'direction': u'ingress', u'remote_ip_prefix': None, u'protocol': u'tcp', u'ethertype': u'IPv4', u'port_range_max': 3389, u'security_group_id': u'778052d3-d9b8-4eee-9ddc-655f185729ff', u'port_range_min': 3389, u'tenant_id': u'7015d1478a4c4bd7b970215d7b0260dd', u'id': u'7054f52e-b284-4f37-a859-e043dbb6393e'}}
https://networking.uk-1.cloud.global.fujitsu.com/v2.0/security-group-rules

{u'security_group_rule': {u'remote_group_id': None, u'direction': u'ingress', u'remote_ip_prefix': None, u'protocol': u'tcp', u'ethertype': u'IPv4', u'port_range_max': 22, u'security_group_id': u'778052d3-d9b8-4eee-9ddc-655f185729ff', u'port_range_min': 22, u'tenant_id': u'7015d1478a4c4bd7b970215d7b0260dd', u'id': u'f70815f8-ac23-43d9-b808-ebf8e12948a2'}}
https://networking.uk-1.cloud.global.fujitsu.com/v2.0/security-group-rules

{u'security_group_rule': {u'remote_group_id': None, u'direction': u'ingress', u'remote_ip_prefix': None, u'protocol': u'icmp', u'ethertype': u'IPv4', u'port_range_max': 0, u'security_group_id': u'778052d3-d9b8-4eee-9ddc-655f185729ff', u'port_range_min': 0, u'tenant_id': u'7015d1478a4c4bd7b970215d7b0260dd', u'id': u'49bdf8b6-618c-4714-b112-7420d815cd83'}}

sbstep9

Paso 9 – Obtengamos un puerto de nuestra nueva subred que se adjuntará al servidor con una llamada a la API como esta –

def create_port(k5token, name, network_id, security_group_id, availability_zone):

    networkURL = unicode(get_endpoint(k5token, "networking")) + unicode('/v2.0/ports')
    print networkURL
    token = k5token.headers['X-Subject-Token']
    try:
        response = requests.post(networkURL,
                                 headers={
                                     'X-Auth-Token': token, 'Content-Type': 'application/json', 'Accept': 'application/json'},
                                 json={"port":
                                       {"network_id": network_id,
                                        "name": name,
                                        "admin_state_up": True,
                                        "availability_zone": availability_zone,
                                        "security_groups":
                                        [security_group_id]}})
        return response
    except:
        return ("\nUnexpected error:", sys.exc_info())

invocada de la siguiente manera –

    # Create a new port for the server
    server_port = create_port(k5token, "demoserverport", network_id, security_group_id, "uk-1b")

    print server_port

    print server_port.json()

    server_port_id = server_port.json()['port'].get('id')

    print server_port_id

produciendo la siguiente salida –

https://networking.uk-1.cloud.global.fujitsu.com/v2.0/ports

{u'port': {u'status': u'DOWN', u'name': u'demoserverport', u'allowed_address_pairs': [], u'admin_state_up': True, u'network_id': u'bc491d0d-56c2-4706-b7b4-6e97029dbeaf', u'tenant_id': u'7015d1478a4c4bd7b970215d7b0260dd', u'availability_zone': u'uk-1b', u'binding:vnic_type': u'normal', u'device_owner': u'', u'mac_address': u'fa:16:3e:60:d6:31', u'fixed_ips': [{u'subnet_id': u'bafdfc08-b55b-4a99-b1c9-2f43cf661a54', u'ip_address': u'192.168.10.2'}], u'id': u'f1db8672-2923-46fb-a65b-4f1e643f5a9e', u'security_groups': [u'7e35e0bc-6254-4ce6-9233-fce162db4a8e'], u'device_id': u''}}
f1db8672-2923-46fb-a65b-4f1e643f5a9e

sbstep10

Paso 10 – Ya casi estamos. La última pieza del rompecabezas antes de poder desplegar un servidor es la clave SSH. Esta siguiente función crea una clave SSH para ti; por favor, asegúrate de almacenar la Clave Privada en algún lugar seguro. K5 solo almacena las claves públicas por diseño.

def create_keypair(k5token, keypair_name, availability_zone):

    computeURL = unicode(get_endpoint(k5token, "compute")) + unicode('/os-keypairs')
    print computeURL
    token = k5token.headers['X-Subject-Token']

    try:
        response = requests.post(computeURL,
                                headers={
                                     'X-Auth-Token': token,
                                     'Content-Type': 'application/json',
                                     'Accept': 'application/json'},
                                json={
                                    "keypair": {
                                        "name": keypair_name,
                                        "availability_zone": availability_zone
                                        }})
        return response
    except:
        return ("\nUnexpected error:", sys.exc_info())

invocada de esta manera –

    # Create ssh key pair that can be injected into the server
    server_key = create_keypair(k5token, "demokeypair", "uk-1b")

    print server_key

    print server_key.json()

    server_key_id = server_key.json()['keypair'].get('id')

    print server_key_id

    server_key_private = server_key.json()['keypair'].get('private_key')

    print server_key_private

    server_key_public = server_key.json()['keypair'].get('public_key')

    print server_key_public

debería producir –

https://compute.uk-1.cloud.global.fujitsu.com/v2/7015d1478a4c4bd7b970215d7b0260dd/os-keypairs

{u'keypair': {u'public_key': u'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAu6R92WdwAgPJrWiwkd+wdHQ61ZX/1PL+yVWUXZ86Of+sHhHFUN2vCj6YfzuqKNJaAYjvy6Mga6rT1VBNyoD5EPryaop7w/1GMzRdZ7UaAwtJnNezu8bG054BVpTJ6vspNYsEGZs0KpggsN5O0f0qa2inxq/jDGTy+Le1qWBaQqB33PPVsH6y8a2DgZmDp6n8BY1DTd32GQzprq7ARfWhNu3nNXYmjAjUe/F1H2z2FmkfTDGvs1Un8ETUdywK7Deh938Nqi7agT7ECYSvawlAjwiBILjx0EsERQJr02dRw/BsgbeLsWY50X3l76tmRaiNE95jDGgzovGDBwm8fIL9LQ== Generated by Nova\n', u'private_key': u'-----BEGIN RSA PRIVATE KEY-----\nMIIEoQIBAAKCAQEAu6R92WdwAgPJrWiwkd+wdHQ61ZX/1PL+yVWUXZ86Of+sHhHF\nUN2vCj6YfzuqKNJaAYjvy6Mga6rT1VBNyoD5EPryaop7w/1GMzRdZ7UaAwtJnNez\nu8bG054BVpTJ6vspNYsEGZs0KpggsN5O0f0qa2inxq/jDGTy+Le1qWBaQqB33PPV\nsH6y8a2DgZmDp6n8BY1DTd32GQzprq7ARfWhNu3nNXYmjAjUe/F1H2z2FmkfTDGv\ns1Un8ETUdywK7Deh938Nqi7agT7ECYSvawlAjwiBILjx0EsERQJr02dRw/BsgbeL\nsWY50X3l76tmRaiNE95jDGgzovGDBwm8fIL9LQIBIwKCAQBAVad9vRB1uCfjrt1z\n16o2jkAOtxXinHSczOJpPegT4qFpZS21U1H04kLpy1BIgqKELvMhPz5QzNrqDOd4\noT9ziT0r17VnxI0Y3sDwW1lgISCNi8iYJuUVWr6hV5WvppHJNvoXaGmoNCh3J6X+\n2nTxoDmF8ylGE/uIeYAc0JP5lYQfHpMkMwG1pLOLf6Eb7OZg752+Dp07jedPabYx\n1i/PIkozmslKbgGM3R2CmhoYEWMKpmoOnPlzb4blRcxCiopSWQuhlj/2EI0sE1hc\n6+NE6pbQ5ddsZmm4DvQTACfy/l8H444DvLOAU2zEOVIp5hkCLP4Yv6YBBjfClqWq\nE7YLAoGBAOE/6AqprnrKzaAcboSiOMW4oidUKFFe9heqJJC54LIqGFyl1qEeJAvt\nllr9DjVA1xY/PRrCtb3D8y5ZJXmHjiRmwT/3UWW/Y0Zy+RkewLbmr0X/jVjk75Ns\n6wTcHlW/6/GEj9ny2ed+kul8IKOH1CFtxEVjiaTGXPy1yvxGSezlAoGBANVCR/My\nkMh/v4JjoWkeqOuyMDqPYFohuO9c6zF6uY5GBtzOcWT/eUQI1i66x/S6Cf2DOd+b\nVZKbobIBUFL36r915MEbkeTe1eHV/dSSmIgfV63qjTnvMLx/QR8VMzIp8+XQz/4z\npfFx96nh45MY9U1fwY3gr5VZl7kEXLJbf5KpAoGBAK3Dlb8VLtPBBQZ8VUG++JiH\nHgEVCSjUOi+DQMdq0eiG35ftpZI70qodroC0le6RGvPnpCqWNG3RrPfeXrzWSRTE\nS++ERhtKf8ih1hqxUtY87ZxmDfQeUmpp9yEBk75+HGnbSmZNoMiGNtFfwWg1lQPY\nVZSdPkvpeu7VYhMRpr4PAoGAc8TlOuDvgskBj+zxORCk17iAlNF9csHZa/892Qgb\nlmCHYexpcVd8WCIN3tpsjCp6c62jEvyNihn4sRan8oaVYJ8Vx+plJHj3w71PR4LH\n1N3QgvurwF1GV7LLlIfZ9qkPX3/74cREI/wKGmSuvZE0tPl3s2tYAJ5ZrZSnWYIg\nrrMCgYBvNCvqchbyDrClZTDJqAm+dpMKAdhKABHpuQUqG3hI+3M/hvjCRmFvLPdZ\nD1LNYXX2xB695iXuwF0Ekyvlf0QajToswSrl3wF06osObJ3iGb1IMtfTmb++JL9d\ncKclHW55JWix70Be6/krDsR6CSGT8Q1DiAJDxYxlzlb496AJ8A==\n-----END RSA PRIVATE KEY-----\n', u'user_id': u'03758af9df694db784c3547ab8217abb', u'name': u'demokeypair', u'fingerprint': u'38:a1:83:52:fd:fa:81:a3:87:3b:01:fc:0f:f1:8a:86'}}
None
-----BEGIN RSA PRIVATE KEY-----
MIIEoQIBAAKCAQEAu6R92WdwAgPJrWiwkd+wdHQ61ZX/1PL+yVWUXZ86Of+sHhHF
UN2vCj6YfzuqKNJaAYjvy6Mga6rT1VBNyoD5EPryaop7w/1GMzRdZ7UaAwtJnNez
u8bG054BVpTJ6vspNYsEGZs0KpggsN5O0f0qa2inxq/jDGTy+Le1qWBaQqB33PPV
sH6y8a2DgZmDp6n8BY1DTd32GQzprq7ARfWhNu3nNXYmjAjUe/F1H2z2FmkfTDGv
s1Un8ETUdywK7Deh938Nqi7agT7ECYSvawlAjwiBILjx0EsERQJr02dRw/BsgbeL
sWY50X3l76tmRaiNE95jDGgzovGDBwm8fIL9LQIBIwKCAQBAVad9vRB1uCfjrt1z
16o2jkAOtxXinHSczOJpPegT4qFpZS21U1H04kLpy1BIgqKELvMhPz5QzNrqDOd4
oT9ziT0r17VnxI0Y3sDwW1lgISCNi8iYJuUVWr6hV5WvppHJNvoXaGmoNCh3J6X+
2nTxoDmF8ylGE/uIeYAc0JP5lYQfHpMkMwG1pLOLf6Eb7OZg752+Dp07jedPabYx
1i/PIkozmslKbgGM3R2CmhoYEWMKpmoOnPlzb4blRcxCiopSWQuhlj/2EI0sE1hc
6+NE6pbQ5ddsZmm4DvQTACfy/l8H444DvLOAU2zEOVIp5hkCLP4Yv6YBBjfClqWq
E7YLAoGBAOE/6AqprnrKzaAcboSiOMW4oidUKFFe9heqJJC54LIqGFyl1qEeJAvt
llr9DjVA1xY/PRrCtb3D8y5ZJXmHjiRmwT/3UWW/Y0Zy+RkewLbmr0X/jVjk75Ns
6wTcHlW/6/GEj9ny2ed+kul8IKOH1CFtxEVjiaTGXPy1yvxGSezlAoGBANVCR/My
kMh/v4JjoWkeqOuyMDqPYFohuO9c6zF6uY5GBtzOcWT/eUQI1i66x/S6Cf2DOd+b
VZKbobIBUFL36r915MEbkeTe1eHV/dSSmIgfV63qjTnvMLx/QR8VMzIp8+XQz/4z
pfFx96nh45MY9U1fwY3gr5VZl7kEXLJbf5KpAoGBAK3Dlb8VLtPBBQZ8VUG++JiH
HgEVCSjUOi+DQMdq0eiG35ftpZI70qodroC0le6RGvPnpCqWNG3RrPfeXrzWSRTE
S++ERhtKf8ih1hqxUtY87ZxmDfQeUmpp9yEBk75+HGnbSmZNoMiGNtFfwWg1lQPY
VZSdPkvpeu7VYhMRpr4PAoGAc8TlOuDvgskBj+zxORCk17iAlNF9csHZa/892Qgb
lmCHYexpcVd8WCIN3tpsjCp6c62jEvyNihn4sRan8oaVYJ8Vx+plJHj3w71PR4LH
1N3QgvurwF1GV7LLlIfZ9qkPX3/74cREI/wKGmSuvZE0tPl3s2tYAJ5ZrZSnWYIg
rrMCgYBvNCvqchbyDrClZTDJqAm+dpMKAdhKABHpuQUqG3hI+3M/hvjCRmFvLPdZ
D1LNYXX2xB695iXuwF0Ekyvlf0QajToswSrl3wF06osObJ3iGb1IMtfTmb++JL9d
cKclHW55JWix70Be6/krDsR6CSGT8Q1DiAJDxYxlzlb496AJ8A==
-----END RSA PRIVATE KEY-----

ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAu6R92WdwAgPJrWiwkd+wdHQ61ZX/1PL+yVWUXZ86Of+sHhHFUN2vCj6YfzuqKNJaAYjvy6Mga6rT1VBNyoD5EPryaop7w/1GMzRdZ7UaAwtJnNezu8bG054BVpTJ6vspNYsEGZs0KpggsN5O0f0qa2inxq/jDGTy+Le1qWBaQqB33PPVsH6y8a2DgZmDp6n8BY1DTd32GQzprq7ARfWhNu3nNXYmjAjUe/F1H2z2FmkfTDGvs1Un8ETUdywK7Deh938Nqi7agT7ECYSvawlAjwiBILjx0EsERQJr02dRw/BsgbeLsWY50X3l76tmRaiNE95jDGgzovGDBwm8fIL9LQ== Generated by Nova

sbstep11

Paso 11 – El que todos hemos estado esperando, el despliegue de la máquina virtual. Para esto notarás que he configurado dos parámetros prerequisito más: el id del sabor o tamaño de camiseta del vCPU y la RAM de la instancia, y el id de la imagen del sistema operativo que utilizaremos. La llamada a la API se ve así –

def create_server_with_port(k5token, name, imageid, flavorid, sshkey_name, security_group_name, availability_zone, volsize,  port_id):

    computeURL = unicode(get_endpoint(k5token, "compute")) + unicode('/servers')
    print computeURL
    token = k5token.headers['X-Subject-Token']
    try:
        response = requests.post(computeURL,
                                headers={'X-Auth-Token':token,'Content-Type': 'application/json','Accept':'application/json'},
                                json={"server": {

                                                 "name": name,
                                                 "security_groups":[{"name": security_group_name }],
                                                 "availability_zone":availability_zone,
                                                 "imageRef": imageid,
                                                 "flavorRef": flavorid,
                                                 "key_name": sshkey_name,
                                                 "block_device_mapping_v2": [{
                                                                               "uuid": imageid,
                                                                               "boot_index": "0",
                                                                               "device_name": "/dev/vda",
                                                                               "source_type": "image",
                                                                               "volume_size": volsize,
                                                                               "destination_type": "volume",
                                                                               "delete_on_termination": True
                                                                            }],
                                                 "networks": [{"port": port_id}],
                                                 "metadata": {"Example Custom Tag": "Finance Department"}
                                                }})

        return response
    except:
        return ("\nUnexpected error:", sys.exc_info())

y se llama de esta manera –

    # K5 predefined parameters for images and flavors

    # this is the id of the K5 ubuntu image
    image_id = "ffa17298-537d-40b2-a848-0a4d22b49df5"

    # the is the id of a small flavor size (T-1 or P1...need to verify)
    flavor_id = "1901"

    # Create the virtual machine
    new_server = create_server_with_port(k5token, "demoserver", image_id, flavor_id, server_key_name, security_group_name, "uk-1b", 3,  server_port_id)

    print new_server

    print new_server.json()

produciendo lo siguiente –

https://compute.uk-1.cloud.global.fujitsu.com/v2/7015d1478a4c4bd7b970215d7b0260dd/servers

{u'server': {u'links': [{u'href': u'http://10.23.0.201/v2/7015d1478a4c4bd7b970215d7b0260dd/servers/5c57d8bc-6c2d-42bf-a84a-77745651b8e4', u'rel': u'self'}, {u'href': u'http://10.23.0.201/7015d1478a4c4bd7b970215d7b0260dd/servers/5c57d8bc-6c2d-42bf-a84a-77745651b8e4', u'rel': u'bookmark'}], u'OS-DCF:diskConfig': u'MANUAL', u'id': u'5c57d8bc-6c2d-42bf-a84a-77745651b8e4', u'security_groups': [{u'name': u'demosecuritygroup'}]}}

¡Y eso es todo! Ahora deberías tener una nueva instancia ejecutándose en K5.
El siguiente paso solo es necesario si deseas adjuntar una dirección ip flotante externa/pública a tu nueva instancia.

sbstep12

Paso 12 – Añadir una dirección ip flotante o global a la nueva máquina virtual utilizando la siguiente llamada a la API –

def create_global_ip(k5token, ext_network_id, port_id, availability_zone):

    networkURL = unicode(get_endpoint(k5token, "networking")) + unicode('/v2.0/floatingips')
    print networkURL
    token = k5token.headers['X-Subject-Token']

    try:
        response = requests.post(networkURL,
                                headers={
                                     'X-Auth-Token': token,
                                     'Content-Type': 'application/json',
                                     'Accept': 'application/json'},
                                json={
                                             "floatingip": {
                                                     "floating_network_id": ext_network_id,
                                                     "port_id": port_id,
                                                     "availability_zone": availability_zone
                                                     },
                                            })
        return response
    except:
        return ("\nUnexpected error:", sys.exc_info())

que debería verse así cuando se invoca –

    # Assign a global/public ip address
    public_ip = create_global_ip(k5token, extaz2, server_port_id, "uk-1b")

    print public_ip

    print public_ip.json()

    print public_ip.json()['floatingip'].get('floating_ip_address')

y producir esto –

https://networking.uk-1.cloud.global.fujitsu.com/v2.0/floatingips

{u'floatingip': {u'router_id': u'4dde5593-6657-4dea-9095-e0f80129e3f4', u'status': u'DOWN', u'availability_zone': u'uk-1b', u'tenant_id': u'7015d1478a4c4bd7b970215d7b0260dd', u'floating_network_id': u'd730db50-0e0c-4790-9972-1f6e2b8c4915', u'fixed_ip_address': u'192.168.10.2', u'floating_ip_address': u'62.60.42.67', u'port_id': u'f5b24292-8a73-4903-afe1-a71da61a18db', u'id': u'77214fa3-e04a-40f6-93a6-400743bb0862'}}
62.60.42.67

sbstep13

¡La dirección ip anterior se puede utilizar para acceder a tu servidor desde internet!

Ten en cuenta que este es deliberadamente un tutorial bastante detallado. También es posible hacer esto sin tantos pasos, es decir, no creando primero un puerto. Esto es para usuarios que requieren ese poco de detalle extra.

La lista completa del tutorial de ejemplo está aquí..

Este archivo contiene texto Unicode oculto o bidireccional que puede interpretarse o compilarse de manera diferente a lo que aparece a continuación. Para revisarlo, abre el archivo en un editor que revele caracteres Unicode ocultos.
Más información sobre caracteres Unicode bidireccionales

Mostrar caracteres ocultos

#!/usr/bin/python
"""Resumen:
El siguiente tutorial demuestra cómo se pueden utilizar las APIs nativas de OpenStack para desplegar un servidor, red, subred y enrutador
en la Plataforma IaaS de Fujitsu K5
Autor: Graham Land
Fecha: 27/01/17
Twitter: @allthingsclowd
Github: https://github.com/allthingscloud
Blog: https://allthingscloud.eu
"""
import requests
import sys
import json
import pprint
def get_endpoint(k5token, endpoint_type):
# listar los puntos de conexión
for ep in k5token.json()['token']['catalog']:
if len(ep['endpoints'])>0:
# si este es el punto de conexión que estoy buscando devuelve la url
if endpoint_type == ep['endpoints'][0].get('name'):
#pprint.pprint(ep)
return ep['endpoints'][0].get('url')
def get_scoped_token(adminUser, adminPassword, contract, projectid, region):
identityURL = 'https://identity.' + region + \
'.cloud.global.fujitsu.com/v3/auth/tokens'
try:
response = requests.post(identityURL,
headers={'Content-Type': 'application/json',
'Accept': 'application/json'},
json={"auth":
{"identity":
{"methods": ["password"], "password":
{"user":
{"domain":
{"name": contract},
"name": adminUser,
"password": adminPassword
}}},
"scope":
{"project":
{"id": projectid
}}}})
return response
except:
return 'Fallo en el alcance del token del proyecto regional'
def create_network(k5token, name, availability_zone):
networkURL = unicode(get_endpoint(k5token, "networking")) + unicode('/v2.0/networks')
print networkURL
token = k5token.headers['X-Subject-Token']
try:
response = requests.post(networkURL,
headers={'X-Auth-Token': token,
'Content-Type': 'application/json'},
json={
"network":
{
"name": name,
"admin_state_up": True,
"availability_zone": availability_zone
}
})
return response
except:
return ("\nError inesperado:", sys.exc_info())
def create_subnet(k5token, name, netid, cidr, availability_zone):
networkURL = unicode(get_endpoint(k5token, "networking")) + unicode('/v2.0/subnets')
print networkURL
token = k5token.headers['X-Subject-Token']
try:
response = requests.post(networkURL,
headers={'X-Auth-Token': token,
'Content-Type': 'application/json'},
json={
"subnet": {
"name": name,
"network_id": netid,
"ip_version": 4,
"cidr": cidr,
"availability_zone": availability_zone
}
})
return response
except:
return ("\nError inesperado:", sys.exc_info())
def create_router(k5token, name, availability_zone):
networkURL = unicode(get_endpoint(k5token, "networking")) + unicode('/v2.0/routers')
print networkURL
token = k5token.headers['X-Subject-Token']
try:
response = requests.post(networkURL,
headers={'X-Auth-Token': token,
'Content-Type': 'application/json'},
json={
"router": {
"name": name,
"admin_state_up": True,
"availability_zone": availability_zone
}})
return response
except:
return ("\nError inesperado:", sys.exc_info())
def update_router_gateway(k5token, router_id, network_id):
networkURL = unicode(get_endpoint(k5token, "networking")) + unicode('/v2.0/routers/') + router_id
print networkURL
token = k5token.headers['X-Subject-Token']
try:
response = requests.put(networkURL,
headers={'X-Auth-Token': token,
'Content-Type': 'application/json'},
json={
"router": {
"external_gateway_info": {
"network_id": network_id
}
}})
return response
except:
return ("\nError inesperado:", sys.exc_info())
def add_interface_to_router(k5token, router_id, subnet_id):
networkURL = unicode(get_endpoint(k5token, "networking")) + unicode('/v2.0/routers/') + router_id + '/add_router_interface'
print networkURL
token = k5token.headers['X-Subject-Token']
try:
response = requests.put(networkURL,
headers={'X-Auth-Token': token,
'Content-Type': 'application/json'},
json={
"subnet_id": subnet_id})
return response
except:
return ("\nError inesperado:", sys.exc_info())
def create_security_group(k5token, name, description):
networkURL = unicode(get_endpoint(k5token, "networking")) + unicode('/v2.0/security-groups')
print networkURL
token = k5token.headers['X-Subject-Token']
try:
response = requests.post(networkURL,
headers={'X-Auth-Token': token, 'Content-Type': 'application/json', 'Accept': 'application/json'},
json={
"security_group": {
"name": name,
"description": description
}
})
return response
except:
return ("\nError inesperado:", sys.exc_info())
def create_security_group_rule(k5token, security_group_id, direction, portmin, portmax, protocol):
networkURL = unicode(get_endpoint(k5token, "networking")) + unicode('/v2.0/security-group-rules')
print networkURL
token = k5token.headers['X-Subject-Token']
try:
response = requests.post(networkURL,
headers={'X-Auth-Token': token, 'Content-Type': 'application/json', 'Accept': 'application/json'},
json={
"security_group_rule": {
"direction": direction,
"port_range_min": portmin,
"ethertype": "IPv4",
"port_range_max": portmax,
"protocol": protocol,
"security_group_id": security_group_id
}
})
return response
except:
return ("\nError inesperado:", sys.exc_info())
def create_port(k5token, name, network_id, security_group_id, availability_zone):
networkURL = unicode(get_endpoint(k5token, "networking")) + unicode('/v2.0/ports')
print networkURL
token = k5token.headers['X-Subject-Token']
try:
response = requests.post(networkURL,
headers={
'X-Auth-Token': token, 'Content-Type': 'application/json', 'Accept': 'application/json'},
json={"port":
{"network_id": network_id,
"name": name,
"admin_state_up": True,
"availability_zone": availability_zone,
"security_groups":
[security_group_id]}})
return response
except:
return ("\nError inesperado:", sys.exc_info())
def create_keypair(k5token, keypair_name, availability_zone):
computeURL = unicode(get_endpoint(k5token, "compute")) + unicode('/os-keypairs')
print computeURL
token = k5token.headers['X-Subject-Token']
try:
response = requests.post(computeURL,
headers={
'X-Auth-Token': token,
'Content-Type': 'application/json',
'Accept': 'application/json'},
json={
"keypair": {
"name": keypair_name,
"availability_zone": availability_zone
}})
return response
except:
return ("\nError inesperado:", sys.exc_info())
def create_server_with_port(k5token, name, imageid, flavorid, sshkey_name, security_group_name, availability_zone, volsize, port_id):
computeURL = unicode(get_endpoint(k5token, "compute")) + unicode('/servers')
print computeURL
token = k5token.headers['X-Subject-Token']
try:
response = requests.post(computeURL,
headers={'X-Auth-Token':token,'Content-Type': 'application/json','Accept':'application/json'},
json={"server": {
"name": name,
"security_groups":[{"name": security_group_name }],
"availability_zone":availability_zone,
"imageRef": imageid,
"flavorRef": flavorid,
"key_name": sshkey_name,
"block_device_mapping_v2": [{
"uuid": imageid,
"boot_index": "0",
"device_name": "/dev/vda",
"source_type": "image",
"volume_size": volsize,
"destination_type": "volume",
"delete_on_termination": True
}],
"networks": [{"port": port_id}],
"metadata": {"Example Custom Tag": "Finance Department"}
}})
return response
except:
return ("\nError inesperado:", sys.exc_info())
def create_global_ip(k5token, ext_network_id, port_id, availability_zone):
networkURL = unicode(get_endpoint(k5token, "networking")) + unicode('/v2.0/floatingips')
print networkURL
token = k5token.headers['X-Subject-Token']
try:
response = requests.post(networkURL,
headers={
'X-Auth-Token': token,
'Content-Type': 'application/json',
'Accept': 'application/json'},
json={
"floatingip": {
"floating_network_id": ext_network_id,
"port_id": port_id,
"availability_zone": availability_zone
},
})
return response
except:
return ("\nError inesperado:", sys.exc_info())
def main():
# Inicializar parámetros del entorno
adminUser = 'username goes here' # nombre de inicio de sesión de usuario k5/openstack
adminPassword = 'password goes here' # contraseña de usuario k5/openstack
contract = 'contract name goes here' # nombre del contrato k5 o nombre del dominio openstack
defaultProject = 'default project name goes here' # id del proyecto predeterminado – en k5 es el nombre del proyecto que comienza con el nombre del contrato y termina con -prj
extaz2 = 'd730db50-0e0c-4790-9972-1f6e2b8c4915' # id de la red externa de la zona de disponibilidad b de K5
demoProjectA = 'target project goes here' # nombre del proyecto objetivo de demostración k5/openstack
demoProjectAid = 'demo project id' # id del proyecto objetivo de demostración k5/openstack
region = 'uk-1' # región objetivo
# Obtener un token vinculado al proyecto
k5token = get_scoped_token(adminUser, adminPassword, contract, demoProjectAid, region)
# Crear una red virtual de capa 2
network = create_network(k5token, "demonet", "uk-1b")
print network
print network.json()
network_id = network.json()['network'].get('id')
print network_id
# Crear una subred de capa 3
subnet = create_subnet(k5token, "demosubnet", network_id, "192.168.10.0/24", "uk-1b")
print subnet
print subnet.json()
subnet_id = subnet.json()['subnet'].get('id')
print subnet_id
# Crear un enrutador virtual de capa 3
router = create_router(k5token, "demorouter", "uk-1b")
print router
print router.json()
router_id = router.json()['router'].get('id')
print router_id
# Añadir puerta de enlace externa al enrutador (extaz2 es el id de la red externa para la red externa en la zona de disponibilidad b)
router_gateway = update_router_gateway(k5token, router_id, extaz2)
print router_gateway
print router_gateway.json()
# Conectar la subred de la nueva red al enrutador
router_interface = add_interface_to_router(k5token, router_id, subnet_id)
print router_interface
print router_interface.json()
# Crear un nuevo grupo de seguridad
security_group = create_security_group(k5token, "demosecuritygroup", "Demo Security Group Allows RDP, SSH and ICMP")
print security_group
print security_group.json()
security_group_id = security_group.json()['security_group'].get('id')
print security_group_id
security_group_name = security_group.json()['security_group'].get('name')
# Crear reglas de grupo de seguridad
# permitir rdp
rdp_rule = create_security_group_rule(k5token, security_group_id, "ingress", "3389", "3389", "tcp")
print rdp_rule
print rdp_rule.json()
# permitir ssh # permitir rdp
ssh_rule = create_security_group_rule(k5token, security_group_id, "ingress", "22", "22", "tcp")
print ssh_rule
print ssh_rule.json()
# permitir icmp
icmp_rule = create_security_group_rule(k5token, security_group_id, "ingress", "0", "0", "icmp")
print icmp_rule
print icmp_rule.json()
# Crear un nuevo puerto para el servidor
server_port = create_port(k5token, "demoserverport", network_id, security_group_id, "uk-1b")
print server_port
print server_port.json()
server_port_id = server_port.json()['port'].get('id')
print server_port_id
# Crear par de claves ssh que se puede inyectar en el servidor
server_key = create_keypair(k5token, "demokeypair", "uk-1b")
print server_key
print server_key.json()
server_key_id = server_key.json()['keypair'].get('id')
print server_key_id
server_key_private = server_key.json()['keypair'].get('private_key')
print server_key_private
server_key_public = server_key.json()['keypair'].get('public_key')
print server_key_public
server_key_name = server_key.json()['keypair'].get('name')
# Parámetros predefinidos de K5 para imágenes y sabores
# este es el id de la imagen ubuntu de K5
image_id = "ffa17298-537d-40b2-a848-0a4d22b49df5"
# este es el id de un tamaño de sabor pequeño (T-1 o P1...necesita verificación)
flavor_id = "1901"
# Crear la máquina virtual
new_server = create_server_with_port(k5token, "demoserver", image_id, flavor_id, server_key_name, security_group_name, "uk-1b", 3, server_port_id)
print new_server
print new_server.json()
# Asignar una dirección ip global/pública
public_ip = create_global_ip(k5token, extaz2, server_port_id, "uk-1b")
print public_ip
print public_ip.json()
print public_ip.json()['floatingip'].get('floating_ip_address')
if __name__ == "__main__":
main()

ver raw
OpenStack_Fujitsu_K5_Server_Build_API_Demo.py
alojado con ❤ por GitHub

o se puede descargar de github aquí..

https://github.com/allthingsclowd/OpenStack_Fujitsu_K5_Server_Build_API_Demo

Asegúrate de configurar los parámetros de entrada ubicados en la función principal para que coincidan con tu entorno objetivo. También hay un script de purga que creé en mi publicación anterior que es bastante útil aquí para las pruebas.

¡Feliz Apilamiento!

withk5youcan

Originally published on allthingscloud.eu (2017-01-27).

← All posts