- 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
V minulých dílech jsme se seznámili s API OneView a jeho ovládání z PowerShell a Python. Dokonce jsme si napsali i pár skriptů. Pojďme dnes využít těchto znalostí a vyzkoušet si nějakou plnější, byť jen jednoduchou ukázkovou aplikaci včetně moderního enterprise GUI.
Kompletní zdrojový kód najdete na https://github.com/tkubica12/oneview-demo/tree/master/grommet-gui
Grommet – HPE GUI v open source projektu
Viděli jste interface nového konvergovaného systému HPE HC 380? Náhled je například v tomto videu:
Kompletní knihovnu pro toto velmi moderní HPE grafické prostředí můžete mít ve svých aplikacích i vy. HPE ho uvolnilo jako samostatný opensource projekt Grommet (http://grommet.github.io/). Na těchto stránkách je kompletní dokumentace tohoto prostředí – jde o HTML5 systém postavený nad React.JS a kromě hotových enterprise ovládacích prvků můžete jednoduše vygenerovat skeleton vašeho frontend a to buď v originálním Grommet designu nebo v barvách HPE (tak jak je to v HC380) nebo designu Aruba.
Python backend pro vytváření Volumů
Abychom nemuseli z GUI volat přímo API OneView, vytvoříme si vlastní webovou službu, která pro nás bude ve OneView vytvářet Volumy. Využijeme tam znalostí z přechozích částí seriálu. Jediné co přidáme je to, že místo skriptu, který se spouští z příkazové řádky to bude webová služba, které parametry přebírá z webového volání. Skript vypadá takhle:
from bottle import route, run, get, post, request, response import json import hpOneView as ov import os username = os.getenv('OV_USERNAME', 'Administrator') password = os.getenv('OV_PASSWORD', 'HPEnet123') oneview_server = os.getenv('OV_SERVER', '192.168.89.100') storage_pool = os.getenv('OV_STORAGE_POOL', 'CPG-SSD') @post('/volume') def volume(): data = request.body.read() volume = json.loads(data)['volume_name'] # Get connection and log into OneView con = ov.connection(oneview_server) login = {'userName':username,'password':password} con.login(login) # Get access to storage resources storage = ov.storage(con) pools = storage.get_storage_pools() for pool in pools['members']: # Find specified storage pool if pool['name'] == storage_pool: storagePoolUri = pool['uri'] newvolume = ov.common.make_storage_volume(volume, 102410241024, True, storagePoolUri, 'Created via script', 'thin') result = storage.add_storage_volume(newvolume) response.headers['Content-Type'] = 'application/json' response.headers['Access-Control-Allow-Origin'] = '*' response.status = 200 print json.dumps({'state': result['state']}) return json.dumps({'state': result['state']}) @get('/volumes') def volume(): count = 0 # Get connection and log into OneView con = ov.connection(oneview_server) login = {'userName':username,'password':password} con.login(login) # Get access to storage resources storage = ov.storage(con) pools = storage.get_storage_pools() for pool in pools['members']: # Find specified storage pool if pool['name'] == storage_pool: existing_volumes = storage.get_storage_volumes() response.headers['Content-Type'] = 'application/json' response.headers['Access-Control-Allow-Origin'] = '*' response.status = 200 print json.dumps({'count': existing_volumes['count']}) return json.dumps({'count': existing_volumes['count']}) run(host='0.0.0.0', port=3000, debug=True)
Nic zásadního se tam neděje jinak, než minule. Parametry pro přihlášení do appliance mají sice nějaké výchozí hodnoty, ale můžeme je změnit nastavením environmentálních proměnných (proč takhle se dozvíte později).
Náš Grommet front-end
V adresáři front-end najdete zdrojový kód námi vytvořeného HTML5 rozhranní s využitím Grommet. Nebudeme se věnovat všem jeho částem (většina je automaticky generovaná), ale na některé se podíváme. Nejprve jak vypadá výsledek?
Tato jednoduchá aplikace tedy nabídne GUI přs které můžete vytvořit Volume určitého názvu a zobrazí vám aktuální počet Volumů ve vaší storage. Jasně – nic zásadně užitečného, ale nám jde teď především o vyzkoušení konceptu – tedy toho, že díky Grommet můžete vytvářet aplikace s velmi moderním HPE-like GUI a využívat jednotné API brány do vaší hardwarové infrastruktury díky OneView.
Logiku aplikace najdete v Dashboard.js.
Takhle vypadá vykreslení grafických elementů:
render () { return ( <Section primary={true}> <Heading tag="h2">Infrastructure as code</Heading> <Paragraph>Create your Volume</Paragraph> <Form onSubmit={this.funkce}> <FormField label="Volume name" htmlFor="volume_name"> <input id="volume_name" type="text" /> </FormField> <Paragraph></Paragraph> <Button label="Create" onClick={this.createVolume}/> </Form> <Paragraph></Paragraph> <Box separator="top"> <Box direction="row" justify="between" pad={{"between": "small"}}> <Paragraph>Volume count in storage:</Paragraph> </Box> <Meter id="meter" type="circle" value={this.state.volumeCount} threshold={90} units="volumes"/> </Box> </Section> ); }
Nic zásadně složitého. A logika, která vytváří volumy a průběžně načítá a vykresluje informace o jejich počtu?
constructor () { super(); this.getVolumes = this.getVolumes.bind(this); this.storeVolumes = this.storeVolumes.bind(this); this.state = { volumeCount: 0, volumeList: ["<ListItem>test</ListItem>", "<ListItem>test2</ListItem>"] }; } createVolume() { console.log(JSON.stringify({ "volume_name": volume_name.value })); var httpRequest; httpRequest = new XMLHttpRequest(); console.log(window.location.hostname); var url = "http://" + window.location.hostname + ":3000/volume"; httpRequest.onreadystatechange = function() { if (httpRequest.readyState === XMLHttpRequest.DONE) { console.log(httpRequest.status); if (httpRequest.status === 200) { console.log(JSON.parse(httpRequest.responseText).state); } else { console.log('There was a problem with the request.'); } } }; httpRequest.open('POST', url, true); httpRequest.send(JSON.stringify({ "volume_name": volume_name.value })); }; storeVolumes (httpRequest) { return function () { if (httpRequest.readyState === XMLHttpRequest.DONE) { console.log(httpRequest.status); if (httpRequest.status === 200) { var count = JSON.parse(httpRequest.responseText).count; this.setState({ volumeCount: count }); } else { console.log('There was a problem with the request.'); } } }.bind(this); }; getVolumes () { var httpRequest; httpRequest = new XMLHttpRequest(); var url = "http://" + window.location.hostname + ":3000/volumes"; httpRequest.onreadystatechange = this.storeVolumes(httpRequest); httpRequest.open('GET', url, true); httpRequest.send(); }; componentDidMount () { window.setInterval(function () { this.getVolumes(); }.bind(this), 2000); };
Detaily tu rozebírat nebudeme, ale nic nekonečně komplikovaného to není.
Zabalíme aplikaci do Docker
Abyste si mohli aplikaci jednoduše sami vyzkoušet, zabalme si obě komponenty do Docker image. Pak vám stačí vzít libovolného Docker hostitele a v něm napsat tento příkaz:
docker run -e "OV_USERNAME=Administrator" -e "OV_PASSWORD=HPEnet123" -e "OV_SERVER=192.168.89.100" -e "OV_STORAGE_POOL=CPG-SSD" -d -p 80:80 -p 3000:3000 --name myapp tomaskubica/grommet-gui
Tím se stáhne potřebný image z veřejného repozotáře a bum – aplikace vám běží. Pokud chcete udělat úpravy v kódu a vytvořit si svůj upravený Docker image, najdete na GitHub a Dockerfile, kterým jednoduše vybudujete nový kontejnerový obraz.