De Zéro à Héros avec l'API IaaS OpenStack de K5 (Python 2.7X)
2017-01-27
Machine-translated from English. Read the English original
Aujourd'hui, je vais passer en revue toutes les étapes nécessaires pour déployer un serveur sur la plateforme IaaS de Fujitsu K5 en utilisant uniquement des appels d'API basés sur OpenStack. J'ai choisi Python 2.7X à des fins de démonstration car c'est sur quoi OpenStack est principalement construit. Cependant, il devrait être suffisamment facile de porter les appels d'API vers un autre langage de script car je n'utilise aucune bibliothèque intermédiaire – toutes mes requêtes http parlent directement aux points de terminaison de K5.
Prérequis pour ce tutoriel :
- Un compte K5 valide avec accès à un projet ou un compte OpenStack valide qui utilise Keystone V3 avec des domaines et l'accès à un projet.
- Le compte doit être un administrateur de projet – c'est-à-dire que vous devez avoir les rôles pour créer et supprimer des ressources au sein du projet.
- Un système Windows ou Linux avec Python 2.7X installé ainsi que le module Requests.
Étapes requises pour créer un serveur à l'aide de l'API OpenStack
Une fois que vous avez satisfait aux prérequis ci-dessus, passons rapidement en revue ce qui est nécessaire pour créer un serveur dans un projet au sein d'OpenStack.

Pour le reste de ce tutoriel, je vais détailler chaque appel d'API en expliquant ce qui est soumis et ce qui est retourné.

Étape 1 – Obtenir un jeton K5 valide étendu au projet dans lequel vous souhaitez déployer le serveur. C'est ici que vous aurez besoin de vos identifiants de connexion K5/OpenStack. Ceux-ci seront fournis avec la requête initiale pour un jeton étendu au projet comme suit :
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 des identifiants valides ont été fournis, vous obtiendrez un objet de réponse JSON qui contient les points de terminaison K5 enregistrés dans son catalogue Keystone OpenStack comme suit :
{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'}}}
Ces informations sont très importantes car lorsque vous souhaitez automatiser pleinement K5, c'est ainsi que vous détectez vos différents points de terminaison pour les services que vous devez consommer.
Remarque : Les points de terminaison qui ont un suffixe « -ex » dans leur nom sont les points de terminaison OpenStack améliorés. Ces points de terminaison incluent les fonctionnalités supplémentaires que Fujitsu a ajoutées à K5 au-delà des fonctionnalités standard d'OpenStack.
Alors, que manque-t-il dans ce tableau... où est le jeton ??? Ne vous inquiétez pas, il est en fait stocké dans l'en-tête de la réponse dans une variable appelée « X-Subject-Token ». Par exemple –
# print the K5 poject scoped token
print "\n\n K5 Project Scoped Token :", k5token.headers['X-Subject-Token'], "\n"
…révèle un jeton, qui, soit dit en passant, est valide pendant 2 heures, comme suit..
K5 Project Scoped Token : f5b72cd06517447fae59360f6deba7d8
Ce jeton doit être transmis avec tous les appels d'API K5 ultérieurs dans l'en-tête pour fournir vos identifiants d'authentification et d'autorisation à chaque demande de service.
L'endpoint standard de l'API OpenStack neutron peut être extrait de la réponse ci-dessus en recherchant l'endpoint appelé « networking ». J'ai utilisé la fonction suivante pour retourner l'URL de l'endpoint que je recherche –
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')
Par exemple –
# list the networking endpoints
print get_endpoint(k5token,"networking")
retournera l'endpoint de l'API neutron dont j'ai besoin –
K5 Networking EndPoints :
https://networking.uk-1.cloud.global.fujitsu.com
Maintenant que nous avons les détails du jeton et de l'endpoint nécessaires, passons à l'étape suivante.

Étape 2 – Créer le réseau de couche 2. L'appel neutron suivant crée un sous-réseau de couche 2 K5 avec les propriétés que vous transmettez via l'API comme suit :
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())
Par exemple –
# Create a layer 2 virtual network
network = create_network(k5token, "demonet", "uk-1b")
print network
print network.json()
produit –
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'}}
Nous devons capturer l'ID du réseau nouvellement créé car nous l'utiliserons dans l'appel d'API suivant –
network_id = network.json()['network'].get('id')
Maintenant, créons notre sous-réseau.

Étape 3 – Créer le sous-réseau de couche 3. Encore une fois, nous utilisons l'appel d'API neutron standard ici et passons le nouvel ID de réseau créé dans l'appel. La fonction utilisée ressemble à ceci –
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())
Et lorsqu'elle est appelée comme suit –
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
produit la réponse suivante –
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
Notez que nous avons maintenant également capturé le nouveau ID de sous-réseau. J'espère que le schéma devient évident maintenant alors que nous passons à l'étape suivante.

Étape 4 – Créer un routeur virtuel. Encore une fois, nous travaillons avec l'endpoint de neutrons OpenStack cette fois en construisant un routeur virtuel. La fonction suivante a été utilisée –
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())
qui, lorsqu'elle est invoquée comme ceci –
# 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
retourne –
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
Encore une fois, nous capturons l'identifiant de la ressource nouvellement créée – router_id.

Étape 5 – Maintenant, configurons le routeur. Tout d'abord, nous définissons la passerelle externe en utilisant l'appel de fonction suivant –
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())
appelé depuis le corps du script comme suit –
# 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()
produisant les résultats suivants –
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'}}

Étape 6 – Nous allons maintenant « brancher » notre réseau virtuel dans notre routeur virtuel avec cet appel de fonction –
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())
qui est invoqué comme ceci –
# 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()
avec la sortie suivante –
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'}
Cela complète les bases de l'infrastructure réseau.

Étape 7 – Le serveur aura besoin d'un groupe de sécurité attribué à ses interfaces réseau, donc nous allons le créer maintenant ainsi que les règles qui permettront les protocoles ssh, tcp et rdp uniquement en entrée.
Cet appel d'API a été utilisé pour créer le groupe de sécurité –
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())
qui est invoqué comme suit –
# 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
résultant en cette sortie –
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

Étape 8 – Créer nos règles de groupe de sécurité avec l'appel d'API suivant –
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())
encore une fois (répétitif, je sais), l'appel est invoqué comme suit –
# 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()
produisant –
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'}}

Étape 9 – Récupérons un port de notre nouveau sous-réseau qui sera attaché au serveur avec un appel d'API comme celui-ci –
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())
invoqué comme suit –
# 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
produisant la sortie suivante –
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

Étape 10 – Nous y sommes presque. La dernière pièce du puzzle avant de pouvoir déployer un serveur est la clé SSH. Cette prochaine fonction crée une clé SSH pour vous – veuillez vous assurer de stocker la clé privée en lieu sûr. K5 ne stocke que les clés publiques par conception.
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())
invoqué de cette manière –
# 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
devrait produire –
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

Étape 11 – Celui pour lequel nous avons tous attendu, le déploiement de la machine virtuelle. Pour cela, vous remarquerez que j'ai configuré deux paramètres prérequis supplémentaires : l'ID de la saveur ou de la taille de t-shirt du vCPU et de la RAM de l'instance, et l'ID de l'image du système d'exploitation que nous utiliserons. L'appel d'API ressemble à ceci –
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())
et est appelé comme ceci –
# 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()
produisant ce qui suit –
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'}]}}
Et c'est tout ! Vous devriez maintenant avoir une nouvelle instance en cours d'exécution sur K5.
L'étape suivante n'est nécessaire que si vous souhaitez attacher une adresse IP flottante externe/publique à votre nouvelle instance.

Étape 12 – Ajouter une adresse IP flottante ou globale à la nouvelle machine virtuelle en utilisant l'appel d'API suivant –
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())
qui devrait ressembler à ceci lorsqu'il est invoqué –
# 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')
et produire ceci –
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

L'adresse IP ci-dessus peut être utilisée pour accéder à votre serveur depuis Internet !
Veuillez noter qu'il s'agit délibérément d'un tutoriel assez détaillé. Il est également possible de le faire sans autant d'étapes, c'est-à-dire sans créer de port en premier. Ceci est destiné aux utilisateurs qui nécessitent ce petit détail supplémentaire.
La liste complète du tutoriel d'exemple est ici..
Ce fichier contient du texte Unicode caché ou bidirectionnel qui peut être interprété ou compilé différemment de ce qui apparaît ci-dessous. Pour examiner, ouvrez le fichier dans un éditeur qui révèle les caractères Unicode cachés.
En savoir plus sur les caractères Unicode bidirectionnels
Afficher les caractères cachés
| #!/usr/bin/python | |
| """Résumé : | |
| Le tutoriel suivant démontre comment les API OpenStack natives peuvent être utilisées pour déployer un serveur, un réseau, un sous-réseau et un routeur | |
| sur la plateforme IaaS Fujitsu K5 | |
| Auteur : Graham Land | |
| Date : 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): | |
| # lister les endpoints | |
| for ep in k5token.json()['token']['catalog']: | |
| if len(ep['endpoints'])>0: | |
| # si c'est l'endpoint que je recherche, retourner l'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 'Échec du ciblage du jeton de projet régional' | |
| 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 ("\nErreur inattendue :", 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 ("\nErreur inattendue :", 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 ("\nErreur inattendue :", 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 ("\nErreur inattendue :", 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 ("\nErreur inattendue :", 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 ("\nErreur inattendue :", 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 ("\nErreur inattendue :", 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 ("\nErreur inattendue :", 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 ("\nErreur inattendue :", 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 ("\nErreur inattendue :", 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 ("\nErreur inattendue :", sys.exc_info()) | |
| def main(): | |
| # Initialiser les paramètres de l'environnement | |
| adminUser = 'username goes here' # nom de connexion utilisateur k5/openstack | |
| adminPassword = 'password goes here' # mot de passe utilisateur k5/openstack | |
| contract = 'contract name goes here' # nom du contrat k5 ou nom du domaine openstack | |
| defaultProject = 'default project name goes here' # ID du projet par défaut – sur k5, c'est le nom du projet qui commence par le nom du contrat et se termine par -prj | |
| extaz2 = 'd730db50-0e0c-4790-9972-1f6e2b8c4915' # ID du réseau externe de la zone de disponibilité b de K5 | |
| demoProjectA = 'target project goes here' # nom du projet cible de démonstration k5/openstack | |
| demoProjectAid = 'demo project id' # ID du projet cible de démonstration k5/openstack | |
| region = 'uk-1' # région cible | |
| # Obtenir un jeton étendu au projet | |
| k5token = get_scoped_token(adminUser, adminPassword, contract, demoProjectAid, region) | |
| # Créer un réseau virtuel de couche 2 | |
| network = create_network(k5token, "demonet", "uk-1b") | |
| print network | |
| print network.json() | |
| network_id = network.json()['network'].get('id') | |
| print network_id | |
| # Créer un sous-réseau de couche 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 | |
| # Créer un routeur virtuel de couche 3 | |
| router = create_router(k5token, "demorouter", "uk-1b") | |
| print router | |
| print router.json() | |
| router_id = router.json()['router'].get('id') | |
| print router_id | |
| # Ajouter une passerelle externe au routeur (extaz2 est l'ID du réseau externe pour le réseau externe dans la zone de disponibilité b) | |
| router_gateway = update_router_gateway(k5token, router_id, extaz2) | |
| print router_gateway | |
| print router_gateway.json() | |
| # Brancher le sous-réseau du nouveau réseau dans le routeur | |
| router_interface = add_interface_to_router(k5token, router_id, subnet_id) | |
| print router_interface | |
| print router_interface.json() | |
| # Créer un nouveau groupe de sécurité | |
| security_group = create_security_group(k5token, "demosecuritygroup", "Groupe de sécurité de démonstration autorisant RDP, SSH et 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') | |
| # Créer des règles de groupe de sécurité | |
| # autoriser rdp | |
| rdp_rule = create_security_group_rule(k5token, security_group_id, "ingress", "3389", "3389", "tcp") | |
| print rdp_rule | |
| print rdp_rule.json() | |
| # autoriser ssh # autoriser rdp | |
| ssh_rule = create_security_group_rule(k5token, security_group_id, "ingress", "22", "22", "tcp") | |
| print ssh_rule | |
| print ssh_rule.json() | |
| # autoriser icmp | |
| icmp_rule = create_security_group_rule(k5token, security_group_id, "ingress", "0", "0", "icmp") | |
| print icmp_rule | |
| print icmp_rule.json() | |
| # Créer un nouveau port pour le serveur | |
| 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 | |
| # Créer une paire de clés ssh qui peut être injectée dans le serveur | |
| 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') | |
| # Paramètres prédéfinis de K5 pour les images et les saveurs | |
| # c'est l'ID de l'image Ubuntu de K5 | |
| image_id = "ffa17298-537d-40b2-a848-0a4d22b49df5" | |
| # c'est l'ID d'une petite taille de saveur (T-1 ou P1...à vérifier) | |
| flavor_id = "1901" | |
| # Créer la machine virtuelle | |
| 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() | |
| # Assigner une adresse IP globale/publique | |
| 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() |
voir brut
OpenStack_Fujitsu_K5_Server_Build_API_Demo.py
hébergé avec ❤ par GitHub
ou peut être téléchargé depuis github ici..
https://github.com/allthingsclowd/OpenStack_Fujitsu_K5_Server_Build_API_Demo
Veuillez vous assurer de configurer les paramètres d'entrée situés dans la fonction principale pour qu'ils correspondent à votre environnement cible. Il y a aussi un script de purge que j'ai créé dans mon article précédent qui est assez pratique ici pour les tests.
Happy Stacking !
withk5youcan
Originally published on allthingscloud.eu (2017-01-27).