- Infrastrukturní DevOps s HPE OneView (1) – Infrastructure as Code
- Infrastrukturní DevOps s HPE OneView (2) – API
- Infrastrukturní DevOps s HPE OneView (3) – Message bus
- Infrastrukturní DevOps s HPE OneView (4) – PowerShell
- Infrastrukturní DevOps s HPE OneView (5) – PowerShell skripty
- Infrastrukturní DevOps s HPE OneView (6) – Python
- Infrastrukturní DevOps s HPE OneView (7) – Python skripty
- Infrastrukturní DevOps s HPE OneView (8) – vaše vlastní aplikace s Grommet
- Infrastrukturní DevOps s HPE OneView (9) – Ansible a infrastruktura
- Infrastrukturní DevOps s HPE OneView (10) – Ansible a Blade networking
- Infrastrukturní DevOps s HPE OneView (11) – Ansible a síťový fabric
- Infrastrukturní DevOps s HPE OneView (12) – Ansible a servery
Infrastrukturní DevOps s HPE OneView (2) – API
Celé Infrastructure as code stojí na schopnosti vyšších nástrojů ovládat infrastrukturu přes nějaké API. Podívejme se, jak můžeme místo nesourodých přístupů použít API pro infrastrukturu, jednotné místo pro compute, storage a networking s HPE OneView.
Jednotné infrastrukturní API
Pokud chcete nainstalovat server, klasicky použijete PXE protokol, TFTP a DHCP server. Jakmile potřebujete vzdáleně ovládat napájení serveru, je to IPMI. K nastavení BIOSu často použijete specifické nízkoúrovňové API (pokud tedy takové máte, další možnost je trefit nějakou F klávesu ve správný okamžik). K založení Volume ve storage dost možná budete muset využít skriptování přes SSH, síť ovládat přes SNMP a takhle můžeme pokračovat dál a dál. Nejen, že každá technologie má API na jiném místě, ale samotná rozhraní jsou diametrálně odlišná. Automatizovat něco takového pak začíná být velmi komplikované.
OneView je nástroj, který se postará o specifické vlastnosti technologií – je to takový překladač. Dává vám k dispozici jedno místo s kompletní sadou API pro ovládání serverů, jejich BIOSů, lokální nastavení storage, připojování a ovládání externích storage, vytváření LAN a SAN připojení a jejich mapování, připojování disků či zónování SAN infrastruktury. Všechno na jednom místě, jedním moderním způsobem (REST API). Džungle nesourodých protokolů a přístupů se schová za nástroj, který vám dá API pro celou infrastrukturu. Vzhledem k nutnosti ovládat nízkoúrovňově hardware není ve OneView k dispozici všechno, co na trhu existuje, ale oblíbené HPE produkty jako jsou rack a blade servery, Synergy, storage 3PAR, síťové prvky HPE, Cisco, Arista či Brocade podporovány jsou. Podpora se stále rozšiřuje.
OneView API
Vyzkoušejme si to. V dnešním díle se to některým z vás bude zdát možná trochu nízkoúrovňové a nepřívětivé. Vězte ale, že pro někoho s drobnou zkušeností v programování je REST API ten nejpříjemnější možný způsob. My nebudeme dnes nic programovat, ale budeme chtít pochopit základní koncepty ovládání a hlavně si udělat představu o možnostech. Když víte co API nabízí, dokážete si představit, co všechno se nad tím dá dělat.
Nejprve se podívejme na dokumentaci. Najdete ji přímo ve svém běžícím OneView na adrese
https://vaše_ip/api-docs/current
REST využívá webových technologií a pro začátek použijeme prográmek cURL, což si představte jako něco na způsob textového “prohlížeče” webu. Nainstalujte si ho jako balíček v Linux (často je v základu přítomen), existuje i verze pro Windows.
Každé volání je reprezentované nějakou URL (ta vede na nějaký objekt) a základním HTTP slovesem, typicky GET pro čtení, POST pro zápis, PUT pro aktualizaci a DELETE pro výmaz. Jednoduché a vše textové, takže i v našem curl si s tím můžeme pohrát. Zkuste tohle:
curl -k https://192.168.89.100/rest/version {"currentVersion":200,"minimumVersion":1}
Co se stalo? Zeptali jsme se v jaké verzi je naše OneView a dostali jsme odpověď. Ta je v programátorsky velice příjemném (přesto lidsky čitelném) formátu JSON. Hranatá závorka reprezentuje objekt a v něm máme dva klíče a dvě hodnoty. Klíč currentVersion má hodnotu 200, tedy používám OneView 2.00. To nebylo složité, že?
Samozřejmě OneView je velmi mocné, takže nesmí fungovat jen tak komukoli – musíme vyžadovat ověření tak, jak to dělá i jeho webový interface. Protože by bylo nepraktické opakovat ověřování kvůli každému zavolání API (vezměte si, že aplikace jich může vygenerovat desítky za vteřinu a to by třeba při napojení na LDAP nebylo ideální), OneView vám vygeneruje token, kterým se budeme dále prokazovat a který platí na období 24 hodin (mimochodem prakticky totéž se děje, když se přihlásíte někam na web).
Použijeme URL na logování a sloveso POST (chceme vytvořit login). Dále musíme poskytnout hlavičku (ta říká, že jsme použili JSON) a předáme OneView data. Těmi je JSON a v našem případě objekt, kde je jméno a heslo pro přihlášení. Zkuste to.
curl -k -X POST https://192.168.89.100/rest/login-sessions \ -H "Content-Type: application/json" \ -d '{"userName":"Administrator","password":"HPEnet123"}' {"sessionID":"NTYwMTEyNDQyMzQxAingR75zJDYXDampdmhO4aLjnJr8-7fO"}
Perfektní, vrátilo se nám sessionID, kterým se budeme dále prokazovat. Pojďme si například vypsat poslední Alert ve OneView. Jak to uděláme? Z dokumentace jsme si našli správné URL. Za něj jsem napsal otazník, který nám umožní přidat vyhledávací parametry (třeba hlášky určité vážnosti, z nějakého systému apod.) a tam jsem řekl, že chci od nejnovější vrátit jen jednu poslední hlášku. Do hlavičky nakopírujeme naše SessionID, specifikujeme v hlavičce verzi API a jdeme na to.
vypsat posledni alert, vysvetlit queury: curl -k "https://192.168.89.100/rest/alerts?start=0&count=1" \ -H "Auth:NTYwMTEyNDQyMzQxAingR75zJDYXDampdmhO4aLjnJr8-7fO" \ -H "X-Api-Version: 200" {"alertSeverityCounts":{"majorCount":0,"criticalCount":0,"unknownCount":0,"okCount":0},"members":[{"type":"AlertResource","resourceUri":"/rest/logical-interconnects/39b4894c-6b05-49c9-a74a-6df9d9d4b57a","physicalResourceType":"logical-interconnects","alertState":"Cleared","severity":"OK","eTag":"2016-08-02T10:59:55.855Z","created":"2016-08-02T10:59:55.855Z","modified":"2016-08-02T10:59:55.855Z","alertTypeID":"crm.uplinkSetStateChange","resourceID":"890579d9-3bea-4def-aed6-e7ab88f7e884","associatedEventUris":["/rest/events/1614"],"assignedToUser":null,"changeLog":[{"notes":"Alert cleared.","userEntered":false,"username":"System","created":"2016-08-02T10:59:55.855Z","uri":"/rest/alerts/AlertChangeLog/268"}],"clearedByUser":"System","clearedTime":"2016-08-02T10:59:55.855Z","correctiveAction":"","urgency":"None","lifeCycle":false,"activityUri":null,"healthCategory":"logical-interconnect","category":"alerts","description":"For uplink set DEV-uplink, all uplink ports are operational.","uri":"/rest/alerts/267"}],"nextPageUri":"/rest/alerts?start=1&count=1&sort=created:descending","start":0,"prevPageUri":null,"total":142,"count":1,"eTag":null,"created":"2016-08-02T11:29:41.031Z","modified":"2016-08-02T11:29:41.031Z","category":"alerts","uri":"/rest/alerts?start=0&count=1&sort=created:descending"}
Funguje! Ale výstup se lidem nečte moc dobře, že. Pokud máte v počítači Python (nainstalujete jednoduše i ve Windows) pošleme výstup do formátovače.
curl -k "https://192.168.89.100/rest/alerts?start=0&count=1" \ -H "Auth:NTYwMTEyNDQyMzQxAingR75zJDYXDampdmhO4aLjnJr8-7fO" \ -H "X-Api-Version: 200" \ | python -mjson.tool { "alertSeverityCounts": { "criticalCount": 0, "majorCount": 0, "okCount": 0, "unknownCount": 0 }, "category": "alerts", "count": 1, "created": "2016-08-02T11:30:40.201Z", "eTag": null, "members": [ { "activityUri": null, "alertState": "Cleared", "alertTypeID": "crm.uplinkSetStateChange", "assignedToUser": null, "associatedEventUris": [ "/rest/events/1614" ], "category": "alerts", "changeLog": [ { "created": "2016-08-02T10:59:55.855Z", "notes": "Alert cleared.", "uri": "/rest/alerts/AlertChangeLog/268", "userEntered": false, "username": "System" } ], "clearedByUser": "System", "clearedTime": "2016-08-02T10:59:55.855Z", "correctiveAction": "", "created": "2016-08-02T10:59:55.855Z", "description": "For uplink set DEV-uplink, all uplink ports are operational.", "eTag": "2016-08-02T10:59:55.855Z", "healthCategory": "logical-interconnect", "lifeCycle": false, "modified": "2016-08-02T10:59:55.855Z", "physicalResourceType": "logical-interconnects", "resourceID": "890579d9-3bea-4def-aed6-e7ab88f7e884", "resourceUri": "/rest/logical-interconnects/39b4894c-6b05-49c9-a74a-6df9d9d4b57a", "severity": "OK", "type": "AlertResource", "urgency": "None", "uri": "/rest/alerts/267" } ], "modified": "2016-08-02T11:30:40.201Z", "nextPageUri": "/rest/alerts?start=1&count=1&sort=created:descending", "prevPageUri": null, "start": 0, "total": 142, "uri": "/rest/alerts?start=0&count=1&sort=created:descending" }
To je lepší. Jak vidíte nemusíme si detailně vysvětlovat JSON, aby jste zhruba pochopili, jaké údaje jsme dostali zpět.
Pohrajme si se storage přes API
Zkusme něco dalšího. Co přes API vytvořit Volume ve storage? Možná už na to je připravena nějaká šablona, tak si je vypišme a najděme její identifikátor (opět URI, tedy v zásadě URL). Na webu vypadá takhle:
a takhle přes API
curl -k "https://192.168.89.100/rest/storage-volume-templates" \ -H "Auth:NTYwMTEyNDQyMzQxAingR75zJDYXDampdmhO4aLjnJr8-7fO" \ -H "X-Api-Version: 200" \ | python -mjson.tool { "category": "storage-volume-templates", "count": 2, "created": "2016-08-02T11:37:21.253Z", "eTag": "2016-08-02T11:37:21.253Z", "members": [ { "category": "storage-volume-templates", "created": "2016-08-02T07:46:53.610Z", "description": "", "eTag": "2016-08-02T07:46:53.610Z", "modified": null, "name": "Boot volume template", "provisioning": { "capacity": "53687091200", "provisionType": "Thin", "shareable": false, "storagePoolUri": "/rest/storage-pools/E7CA0DC4-B982-4140-8C78-B12BD676359D" }, "refreshState": "NotRefreshing", "state": "Configured", "stateReason": "None", "status": "OK", "storageSystemUri": "/rest/storage-systems/TXQ1000307", "type": "StorageVolumeTemplate", "uri": "/rest/storage-volume-templates/4679410e-18c7-408e-97e4-30946ed3b29a" }, { "category": "storage-volume-templates", "created": "2016-08-02T07:47:03.000Z", "description": "", "eTag": "2016-08-02T07:47:03.000Z", "modified": null, "name": "Data disk template", "provisioning": { "capacity": "10737418240", "provisionType": "Thin", "shareable": false, "storagePoolUri": "/rest/storage-pools/E7CA0DC4-B982-4140-8C78-B12BD676359D" }, "refreshState": "NotRefreshing", "state": "Configured", "stateReason": "None", "status": "OK", "storageSystemUri": "/rest/storage-systems/TXQ1000307", "type": "StorageVolumeTemplate", "uri": "/rest/storage-volume-templates/cd0c3cec-f23b-45e1-972d-1b2899aab620" } ], "modified": "2016-08-02T11:37:21.253Z", "nextPageUri": null, "prevPageUri": null, "start": 0, "total": 2, "type": "StorageVolumeTemplateList", "uri": "/rest/storage-volume-templates" }
Poznamenejme si uri šablony dle našeho výběru a podívejme se, jestli máme ve storage nějaký Volume.
Na webu nemám žádný.
Co přes API?
curl -k "https://192.168.89.100/rest/storage-volumes" \ -H "Auth:NTYwMTEyNDQyMzQxAingR75zJDYXDampdmhO4aLjnJr8-7fO" \ -H "X-Api-Version: 200" \ | python -mjson.tool { "category": "storage-volumes", "count": 0, "created": "2016-08-02T11:41:04.955Z", "eTag": "2016-08-02T11:41:04.955Z", "members": [], "modified": "2016-08-02T11:41:04.955Z", "nextPageUri": null, "prevPageUri": null, "start": 0, "total": 0, "type": "StorageVolumeListV3", "uri": "/rest/storage-volumes" }
Jak vidno u mě tam žádný není. Vytvořme jej. URL příkazu je stejné, jen místo slovesa pro čtení použijeme to zapisovací (POST) a poskytneme informace o Volume, který chceme vytvořit.
curl -k -X POST "https://192.168.89.100/rest/storage-volumes" \ -H "Auth:NTYwMTEyNDQyMzQxAingR75zJDYXDampdmhO4aLjnJr8-7fO" \ -H "Content-Type: application/json" \ -H "X-Api-Version: 200" \ -d '{ "name": "Volume-pres-API", "description": "Tohle je muj volume z API", "templateUri": "/rest/storage-volume-templates/cd0c3cec-f23b-45e1-972d-1b2899aab620", "provisioningParameters": { "shareable": true, "requestedCapacity": "987654321" } }' \ | python -mjson.tool { "associatedResource": { "associationType": "MANAGED_BY", "resourceCategory": "storage-volumes", "resourceName": null, "resourceUri": null }, "associatedTaskUri": null, "category": "tasks", "completedSteps": 0, "computedPercentComplete": 0, "created": "2016-08-02T11:49:59.480Z", "data": null, "eTag": "0", "expectedDuration": 0, "hidden": false, "modified": "2016-08-02T11:49:59.480Z", "name": "Create", "owner": "Administrator", "parentTaskUri": null, "percentComplete": 0, "progressUpdates": [], "stateReason": null, "taskErrors": [], "taskOutput": [], "taskState": "New", "taskStatus": "Creating", "taskType": "User", "totalSteps": 6, "type": "TaskResourceV2", "uri": "/rest/tasks/138640AA-9951-425A-B071-1F47F36B6978", "userInitiated": true }
Podívejte do GUI na Volumy – není tak nějaký nový?
Když si teď vypíšeme Volumy přes API, určitě tam bude.
curl -k "https://192.168.89.100/rest/storage-volumes" \ -H "Auth:NTYwMTEyNDQyMzQxAingR75zJDYXDampdmhO4aLjnJr8-7fO" \ -H "X-Api-Version: 200" \ | python -mjson.tool { "category": "storage-volumes", "count": 1, "created": "2016-08-02T11:51:10.045Z", "eTag": "2016-08-02T11:51:10.045Z", "members": [ { "allocatedCapacity": "536870912", "category": "storage-volumes", "created": "2016-08-02T11:49:59.537Z", "description": "Tohle je muj volume z API", "deviceType": "SSD", "deviceVolumeName": "Volume-pres-API", "eTag": "2016-08-02T11:50:00.646Z", "isPermanent": true, "modified": "2016-08-02T11:50:00.646Z", "name": "Volume-pres-API", "provisionType": "Thin", "provisionedCapacity": "976224256", "raidLevel": "RAID5", "refreshState": "NotRefreshing", "revertToSnapshotUri": null, "shareable": true, "snapshotPoolUri": "/rest/storage-pools/E7CA0DC4-B982-4140-8C78-B12BD676359D", "snapshots": null, "state": "Configured", "stateReason": "None", "status": "OK", "storagePoolUri": "/rest/storage-pools/E7CA0DC4-B982-4140-8C78-B12BD676359D", "storageSystemUri": "/rest/storage-systems/TXQ1000307", "type": "StorageVolumeV3", "uri": "/rest/storage-volumes/1B0AC7CE-36A0-4FBF-91D5-0DCD6FB699D9", "wwn": "DC:37:34:64:21:00:10:00:30:71:47:01:38:60:00:39" } ], "modified": "2016-08-02T11:51:10.045Z", "nextPageUri": null, "prevPageUri": null, "start": 0, "total": 1, "type": "StorageVolumeListV3", "uri": "/rest/storage-volumes" }
Jednoduše ho můžeme zase smazat. V předchozím výpisu vidíte identifikátor (tedy uri) naší storage. Stačí tedy jejím směrem poslat sloveso DELETE.
curl -k -X DELETE https://192.168.89.100//rest/storage-volumes/1B0AC7CE-36A0-4FBF-91D5-0DCD6FB699D9 \ -H "Auth:NTYwMTEyNDQyMzQxAingR75zJDYXDampdmhO4aLjnJr8-7fO" \ -H "X-Api-Version: 200" \ | python -mjson.tool { "associatedResource": { "associationType": "MANAGED_BY", "resourceCategory": "storage-volumes", "resourceName": null, "resourceUri": null }, "associatedTaskUri": null, "category": "tasks", "completedSteps": 0, "computedPercentComplete": 0, "created": "2016-08-02T11:54:07.486Z", "data": null, "eTag": "0", "expectedDuration": 0, "hidden": false, "modified": "2016-08-02T11:54:07.486Z", "name": "Delete", "owner": "Administrator", "parentTaskUri": null, "percentComplete": 0, "progressUpdates": [], "stateReason": null, "taskErrors": [], "taskOutput": [], "taskState": "New", "taskStatus": "Deleting", "taskType": "User", "totalSteps": 3, "type": "TaskResourceV2", "uri": "/rest/tasks/D9AACB8B-4039-4AA7-96B2-2863583543DD", "userInitiated": true }
Pro dnešek hotovo, můžeme zrušit svoje přihlášení (sessionID). Stejné URL jako při přihlašování, ale místo vytvářecího slovesa POST pošleme DELETE.
curl -k -X DELETE https://192.168.89.100/rest/login-sessions \ -H "Auth:NTYwMTEyNDQyMzQxAingR75zJDYXDampdmhO4aLjnJr8-7fO"
Podívejte se do GUI na logování aktivity. Najdete tam, co naše API volání dělala.