- 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ém díle jsme se seznámili se základním popisem infrastruktury v YAML a ukázali jsme si tři role, které budeme používat. Dnes prozkoumáme detaily první z nich – Blade networking.
Role vs. Playbook/Task vs. Module
Ansible má hierarchii abstrakcí. To co dělat nemusíme je psát modul, to za nás udělali zaměstnanci HPE a stáhneme si to jako open source z GitHub. Jde o vytvoření základních OneView operací. Pro nás to jsou hotové věci, ale pod kapotou je Python kód, který je transformuje do jednotlivých API volání. Tím se ale trápit nemusíme.
V minulém díle jsme viděli top level YAML soubor, kde jsme pouze určili role a přiřadili jim soubor s nastavením infrastruktury. Role jsou vyšší míra abstrakce. Existuje jejich repozitář, můžete je stahovat i sdílet. Pro tuto ukázku jsem si ovšem role připravil sám.
Co role ov-networking dělá a jak
Podívejme se společně do main.yaml v rámci role on-networking/tasks. První krok je tento:
- name: Ensure that Networks exist oneview_ethernet_network: config: "{{ oneview_config_file }}" state: "{{ state }}" data: name: "{{ item.name }}" vlanId: "{{ item.id }}" smartLink: true privateNetwork: false purpose: General with_items: "{{ vlans }}" register: networks
Nejprve se tedy potřebujeme ujistit, že sítě, které požadujeme, skutečně ve OneView existují. Používáme OneView příkaz oneview_ethernet_network. Config obsahuje přihlašovací údaje a v state máme ve výchozím stavu present, tedy chceme sítě mít. Pokud nejsou, mají se vytvořit. Pokud dáte stav absent, bude to fungovat opačně.
Ještě než se dostaneme k části data musím zmínit with_items. To je něco, co byste v programování označili jako cyklus typu for each. Příkaz chceme provést pro každou požadovanou VLAN. A kde se tyto berou? No to je z našeho předpisu infrastruktury (config.yaml), který jsme rozebrali minule – konkrétně tato část:
vlans: - id: 101 name: Prod-101 - id: 102 name: Prod-102 - id: 103 name: Dev-103
Teď se můžeme podívat do části data. Tam jsou parametry pro jednotlivá volání příkazu oneview_ethernet_network. Místo fixních parametrů občas dosazujeme item (což je políčko, na kterém se cyklus zrovna nachází) a za tečkou je klíč, tedy buď id nebo name. Takže při první volání příkazu bude item.id=101 a item.name=Prod-101 a tak postupně dál. Poslední, co musíme okomentovat, je slovíčko register. Jde o to, že každé volání příkazu nám současně vrátilo nějaké informace a některé z nich budeme potřebovat dál. Proto si veškeré výstupy registrujeme do proměnné networks.
Podívejme se na druhý krok.
- name: Store network URIs in list set_fact: network_uris: "{{ networks.results | map(attribute='ansible_facts.ethernet_network.uri') | list }}"
Tohle je technikálie. Pro další příkazy potřebuji URI sítí seřazené v seznamu. Výstupy předchozího příkazu obsahují hromadu dalších informací. Zabudovaným Ansible příkazem set_fact přetransformujeme informace z networks do pouhého seznamu URI uloženého v network_uris.
Jdeme dál. Teď potřebujeme tyto sítě přidat na naší skupinu logických interconnectů a tu máme popsanou v našem config-yaml.
- name: Ensure networks are present on Logical interconnect group oneview_logical_interconnect_group: config: "{{ oneview_config_file }}" state: present data: type: "logical-interconnect-groupV3" name: "{{ logical_interconnect_group }}" internalNetworkUris: "{{ network_uris }}"
Poslední v tomto souboru je rekurzivní příkaz. Chceme vyvolat playbook uplinksets.yaml tak, že pokaždé mu pošleme konkrétní hodnoty ze seznamu connectivity_enclosures.
- name: Ensure UplinkSets are configured include: uplinksets.yaml with_items: "{{ connectivity_enclosures }}"
Připomeňme si tuto část našeho config.yaml.
connectivity_enclosures: - logical_interconnects: - module: Encl1, interconnect 1 ports: - X2 - X4 switchports: - GigabitEthernet 1/0/2 - GigabitEthernet 1/0/3 switch_link_aggregation_group: 1 - module: Encl1, interconnect 2 ports: - X2 - X4 switchports: - GigabitEthernet 1/0/4 - GigabitEthernet 1/0/5 switch_link_aggregation_group: 2 - logical_interconnects: - module: Encl2, interconnect 1 ports: - X2 - X4 switchports: - GigabitEthernet 1/0/6 - GigabitEthernet 1/0/7 switch_link_aggregation_group: 3 - module: Encl2, interconnect 2 ports: - X2 - X4 switchports: - GigabitEthernet 1/0/8 - GigabitEthernet 1/0/9
V každém volání tedy dostaneme jeden konkrétní modul a seznam jeho portů.
Pro každý modul a seznam portů tedy budeme dělat následující kroky.
Nejprve provedeme řadu přípravných prací. Poskládáme si parametry do správné formy, vytvoříme JSON strukturu s nastavením portu a tak podobně.
- name: Create map with facts about interconnects oneview_interconnect_facts: config: "{{ oneview_config_file }}" name: "{{ item.module }}" with_items: "{{ item.logical_interconnects }}" register: interconnects_map - name: Build port configurations set_fact: port_config: '{ "desiredSpeed": "Auto", "location": { "locationEntries": [ { "type": "Port", "value": "{{ item[1] }}" }, {{ item[0].ansible_facts.interconnects[0].interconnectLocation.locationEntries[0] }}, {{ item[0].ansible_facts.interconnects[0].interconnectLocation.locationEntries[1] }} ] } }' with_subelements: - "{{ interconnects_map.results }}" - "item.ports" register: port_map - name: Map port configurations to JSON array set_fact: port_configs: "{{ port_map.results | map(attribute='ansible_facts.port_config') | list }}" - name: Get Logical Interconnect URI set_fact: l_interconnect: "{{ interconnects_map.results[0].ansible_facts.interconnects[0].logicalInterconnectUri }}"
Všechno je připraveno, takže můžeme zavolat příkaz oneview_uplink_set. V datové části mu posíláme seznam sítí, které na portech chceme mít a také jednotlivé konfigurace požadovaných portů, které jsme si připravili v předchozím kroku.
- name: Ensure that the Uplink Set with Networks is present oneview_uplink_set: config: "{{ oneview_config_file }}" state: "{{ state }}" data: type: "uplink-setV3" name: "Ansible-uplink{{ interconnects_map.results[0].ansible_facts.interconnects[0].name }}" status: "OK" logicalInterconnectUri: "{{ l_interconnect }}" networkUris: "{{ network_uris }}" fcNetworkUris: [] fcoeNetworkUris: [] portConfigInfos: "{{ port_configs }}" connectionMode: "Auto" networkType: "Ethernet" manualLoginRedistributionState: "NotSupported"
A máme hotovo ! Sítě ve OneView jsou vytvořené a přiřazené na správné moduly a porty podle toho, co jsme si napsali v config.yaml. Chcete přidat další VLAN? Stačí ji připsat do config.yaml a spustit vše znovu. Ansible ji přidá všude, kde je potřeba. Potřebujete přidat další externí port, kde budou sítě nastavené? Připiště ho do seznamu a spusťte Ansible znova.
Dnes jsme si rozebrali první roli, která nastavuje networking v blade chassis přes OneView. Příště se podíváme na druhou roli, která nastavuje připojený top-of-rack síťový prvek, v našem případě HPE 5900 s Comware.