├── Gemfile ├── examples ├── cookbooks │ ├── my_apache_server │ │ ├── Berksfile │ │ ├── spec │ │ │ ├── spec_helper.rb │ │ │ └── unit │ │ │ │ └── recipes │ │ │ │ └── default_spec.rb │ │ ├── CHANGELOG.md │ │ ├── Gemfile │ │ ├── files │ │ │ └── default │ │ │ │ └── oneview │ │ │ │ ├── assets │ │ │ │ ├── chef-logo.png │ │ │ │ └── banner-option-2.jpg │ │ │ │ └── index.html │ │ ├── .kitchen.yml │ │ ├── .gitignore │ │ ├── metadata.rb │ │ ├── templates │ │ │ └── default │ │ │ │ ├── index.html.erb │ │ │ │ └── custom.erb │ │ ├── README.md │ │ ├── recipes │ │ │ └── default.rb │ │ └── chefignore │ └── provisioning_cookbook │ │ ├── Berksfile │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── Gemfile │ │ ├── .kitchen.yml │ │ ├── .gitignore │ │ ├── recipes │ │ ├── install_gems.rb │ │ ├── zero.rb │ │ └── default.rb │ │ ├── metadata.rb │ │ ├── README.md │ │ └── chefignore ├── Berksfile ├── Gemfile ├── .gitignore ├── Docker │ └── Dockerfile ├── Docker_RPI │ └── Dockerfile ├── ssl_issues.md ├── install_ssl_certs.rb ├── .chef │ └── knife.rb.example ├── README.md └── ICsp │ └── chef-settings-linux ├── spec ├── support │ ├── fixtures │ │ ├── icsp │ │ │ └── v102 │ │ │ │ ├── version.json │ │ │ │ ├── login.json │ │ │ │ ├── os-deployment-servers_fakesn.json │ │ │ │ ├── error_404.json │ │ │ │ ├── server_by_sn_empty.json │ │ │ │ ├── server_by_sn_VCGE9KB041.json │ │ │ │ ├── os-deployment-servers_1670001.json │ │ │ │ ├── os-deployment-build-plans.json │ │ │ │ └── os-deployment-servers.json │ │ └── oneview │ │ │ ├── v120 │ │ │ ├── version.json │ │ │ ├── login.json │ │ │ ├── tasks_fake_active.json │ │ │ ├── tasks_fake_complete.json │ │ │ ├── error_404.json │ │ │ ├── server-profiles_invalid_filter.json │ │ │ ├── server-profiles_name_empty.json │ │ │ ├── server-profiles_sn_empty.json │ │ │ ├── storage-volumes_1B5D3CA2-6C5B-41C2-8B97-1821F1883F22.json │ │ │ ├── server-profiles_name_Template-WebServer.json │ │ │ ├── server-profiles_name_chef-web01.json │ │ │ ├── server-profiles_name_chef-web03.json │ │ │ ├── server-profiles_sn_VCGE9KB041.json │ │ │ ├── server-hardware_specific.json │ │ │ ├── server_profile_web01_with_san_unparsed.json │ │ │ ├── server_profile_web01_with_san.json │ │ │ ├── server-profiles_name_Template-WebServerWithSAN.json │ │ │ └── server-profiles_sn_VCGE9KB042.json │ │ │ └── v200 │ │ │ ├── version.json │ │ │ ├── server-profile-templates_invalid.json │ │ │ ├── server-profile-templates_WebServerTemplate.json │ │ │ ├── server-profile-templates_new-profile_WebServerTemplate.json │ │ │ ├── server-profile-templates_WebServerTemplateWithSAN.json │ │ │ ├── server-profile-templates_new-profile_WebServerTemplateWithSAN.json │ │ │ └── server_profile_web01_with_san_unparsed.json │ ├── fake_action_handler.rb │ ├── fake_response.rb │ ├── fake_machine_spec.rb │ ├── fake_icsp.rb │ └── fake_oneview.rb ├── unit │ ├── icsp_search_spec.rb │ ├── icsp_helper_spec.rb │ ├── rest_api_spec.rb │ ├── create_machine_spec.rb │ ├── oneview_san_spec.rb │ └── oneview_helper_spec.rb ├── spec_helper.rb └── shared_context.rb ├── lib └── chef │ └── provisioning │ ├── version.rb │ ├── driver_init │ └── oneview.rb │ ├── helpers.rb │ ├── icsp │ ├── api_v104.rb │ └── rest.rb │ ├── create_machine.rb │ ├── oneview │ ├── oneview_helper.rb │ └── san_storage.rb │ └── customize_machine.rb ├── .travis.yml ├── .gitignore ├── Rakefile ├── LICENSE ├── .rubocop.yml ├── chef-provisioning-oneview.gemspec └── README.md /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec 4 | -------------------------------------------------------------------------------- /examples/cookbooks/my_apache_server/Berksfile: -------------------------------------------------------------------------------- 1 | source "https://supermarket.chef.io" 2 | metadata 3 | -------------------------------------------------------------------------------- /examples/cookbooks/provisioning_cookbook/Berksfile: -------------------------------------------------------------------------------- 1 | source "https://supermarket.chef.io" 2 | metadata 3 | -------------------------------------------------------------------------------- /spec/support/fixtures/icsp/v102/version.json: -------------------------------------------------------------------------------- 1 | { 2 | "minimumVersion": 1, 3 | "currentVersion": 102 4 | } -------------------------------------------------------------------------------- /examples/cookbooks/my_apache_server/spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'chefspec' 2 | require 'chefspec/berkshelf' 3 | -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v120/version.json: -------------------------------------------------------------------------------- 1 | { 2 | "minimumVersion": 1, 3 | "currentVersion": 120 4 | } -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v200/version.json: -------------------------------------------------------------------------------- 1 | { 2 | "minimumVersion": 1, 3 | "currentVersion": 200 4 | } -------------------------------------------------------------------------------- /examples/cookbooks/provisioning_cookbook/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 0.1.0 2 | 3 | Initial release of provisioning_cookbook 4 | -------------------------------------------------------------------------------- /examples/Berksfile: -------------------------------------------------------------------------------- 1 | source 'https://supermarket.chef.io' 2 | 3 | cookbook 'my_apache_server', path: './cookbooks/my_apache_server' 4 | -------------------------------------------------------------------------------- /spec/support/fixtures/icsp/v102/login.json: -------------------------------------------------------------------------------- 1 | { 2 | "partnerData": { 3 | }, 4 | "sessionID": "AA_aaAaa3AA3Aa0_aAaAA4AAAA3AAAAA" 5 | } -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v120/login.json: -------------------------------------------------------------------------------- 1 | { 2 | "partnerData": { 3 | }, 4 | "sessionID": "A954A2A6Psy7Alg3HApAcEbAcAwa-ftA" 5 | } -------------------------------------------------------------------------------- /lib/chef/provisioning/version.rb: -------------------------------------------------------------------------------- 1 | class Chef 2 | module Provisioning 3 | ONEVIEW_DRIVER_VERSION = '1.3.0'.freeze 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /examples/cookbooks/my_apache_server/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 0.1.0 2 | 3 | Initial release of my_apache_server 4 | 5 | # 0.1.1 6 | 7 | Updated web page 8 | -------------------------------------------------------------------------------- /examples/cookbooks/provisioning_cookbook/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) Hewlett Packard Enterprise 2 | 3 | All rights reserved - Do Not Redistribute 4 | -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v120/tasks_fake_active.json: -------------------------------------------------------------------------------- 1 | { 2 | "taskState": "active", 3 | "taskStatus": "active", 4 | "running": "true" 5 | } -------------------------------------------------------------------------------- /examples/cookbooks/my_apache_server/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'berkshelf' 4 | gem "test-kitchen" 5 | gem "kitchen-vagrant" 6 | -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v120/tasks_fake_complete.json: -------------------------------------------------------------------------------- 1 | { 2 | "taskState": "completed", 3 | "taskStatus": "completed", 4 | "running": "false" 5 | } -------------------------------------------------------------------------------- /examples/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # gem 'chef-dk', '~> 0.12' 4 | gem 'berkshelf', '> 4.0' 5 | gem 'chef-provisioning-oneview', '= 1.3.0' 6 | gem 'ridley' 7 | -------------------------------------------------------------------------------- /lib/chef/provisioning/driver_init/oneview.rb: -------------------------------------------------------------------------------- 1 | require 'chef/provisioning/oneview_driver' 2 | 3 | Chef::Provisioning.register_driver_class('oneview', Chef::Provisioning::OneViewDriver) 4 | -------------------------------------------------------------------------------- /spec/support/fake_action_handler.rb: -------------------------------------------------------------------------------- 1 | module ChefProvisioningOneviewHelpers 2 | class FakeActionHandler < Chef::Provisioning::ActionHandler 3 | def puts(*) 4 | end 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | sudo: false 3 | 4 | rvm: 5 | - 2.1 6 | - 2.2 7 | - 2.3.1 8 | 9 | before_install: gem update bundler 10 | 11 | script: 12 | - rake build 13 | - rake test 14 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | Berksfile.lock 8 | nodes/ 9 | clients/ 10 | .chef/knife.rb 11 | .chef/local-mode-cache/ 12 | .chef/trusted_certs/ 13 | *.pem 14 | -------------------------------------------------------------------------------- /examples/cookbooks/my_apache_server/files/default/oneview/assets/chef-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HewlettPackard/chef-provisioning-oneview/HEAD/examples/cookbooks/my_apache_server/files/default/oneview/assets/chef-logo.png -------------------------------------------------------------------------------- /examples/cookbooks/provisioning_cookbook/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'berkshelf' 4 | gem 'test-kitchen' 5 | gem 'kitchen-vagrant' 6 | gem 'chefspec' 7 | gem 'foodcritic' 8 | gem 'chef-provisioning-oneview' 9 | -------------------------------------------------------------------------------- /examples/cookbooks/my_apache_server/files/default/oneview/assets/banner-option-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HewlettPackard/chef-provisioning-oneview/HEAD/examples/cookbooks/my_apache_server/files/default/oneview/assets/banner-option-2.jpg -------------------------------------------------------------------------------- /examples/Docker/Dockerfile: -------------------------------------------------------------------------------- 1 | # Docker file to build ChefDK with HPE OneView provisioning driver 2 | FROM centos:latest 3 | MAINTAINER 4 | 5 | RUN curl -L https://www.opscode.com/chef/install.sh | bash -s -- -P chefdk 6 | RUN chef gem install chef-provisioning-oneview 7 | -------------------------------------------------------------------------------- /examples/cookbooks/provisioning_cookbook/.kitchen.yml: -------------------------------------------------------------------------------- 1 | --- 2 | driver: 3 | name: vagrant 4 | 5 | provisioner: 6 | name: chef_zero 7 | 8 | platforms: 9 | - name: ubuntu-14.04 10 | - name: centos-6.7 11 | 12 | suites: 13 | - name: default 14 | run_list: 15 | 16 | attributes: 17 | -------------------------------------------------------------------------------- /examples/cookbooks/my_apache_server/.kitchen.yml: -------------------------------------------------------------------------------- 1 | --- 2 | driver: 3 | name: vagrant 4 | 5 | provisioner: 6 | name: chef_zero 7 | 8 | platforms: 9 | - name: centos-6.5 10 | 11 | suites: 12 | - name: default 13 | run_list: 14 | - recipe[my_apache_server::default] 15 | attributes: 16 | -------------------------------------------------------------------------------- /examples/Docker_RPI/Dockerfile: -------------------------------------------------------------------------------- 1 | # Docker file to build Chef-Zero on Raspberry Pi with HPE OneView 2 | 3 | FROM armv7/armhf-debian:latest 4 | MAINTAINER 5 | 6 | RUN apt-get update 7 | RUN apt-get -y install chef-zero ruby2.1-dev gcc make 8 | RUN chef gem install chef-provisioning-oneview 9 | -------------------------------------------------------------------------------- /examples/cookbooks/my_apache_server/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *# 3 | .#* 4 | \#*# 5 | .*.sw[a-z] 6 | *.un~ 7 | pkg/ 8 | 9 | # Berkshelf 10 | .vagrant 11 | /cookbooks 12 | 13 | Berksfile.lock 14 | 15 | 16 | # Bundler 17 | Gemfile.lock 18 | bin/* 19 | .bundle/* 20 | 21 | 22 | .kitchen/ 23 | .kitchen.local.yml 24 | -------------------------------------------------------------------------------- /examples/cookbooks/provisioning_cookbook/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *# 3 | .#* 4 | \#*# 5 | .*.sw[a-z] 6 | *.un~ 7 | pkg/ 8 | 9 | # Berkshelf 10 | .vagrant 11 | /cookbooks 12 | 13 | Berksfile.lock 14 | 15 | 16 | # Bundler 17 | Gemfile.lock 18 | bin/* 19 | .bundle/* 20 | 21 | 22 | .kitchen/ 23 | .kitchen.local.yml 24 | -------------------------------------------------------------------------------- /spec/support/fixtures/icsp/v102/os-deployment-servers_fakesn.json: -------------------------------------------------------------------------------- 1 | { 2 | "details": "", 3 | "errorSource": null, 4 | "nestedErrors": [], 5 | "recommendedActions": ["Verify that the server has not been deleted."], 6 | "errorCode": null, 7 | "data": {}, 8 | "message": "The server ID \"FAKESN\" is not valid." 9 | } 10 | -------------------------------------------------------------------------------- /examples/cookbooks/provisioning_cookbook/recipes/install_gems.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: provisioning_cookbook 3 | # Recipe:: default 4 | # 5 | # Copyright (C) Hewlett Packard Enterprise 6 | # 7 | # All rights reserved - Do Not Redistribute 8 | # 9 | 10 | chef_gem 'chef-provisioning-oneview' do 11 | compile_time true 12 | end 13 | -------------------------------------------------------------------------------- /examples/cookbooks/provisioning_cookbook/metadata.rb: -------------------------------------------------------------------------------- 1 | name 'provisioning_cookbook' 2 | maintainer 'Jared Smartt' 3 | maintainer_email 'jared.smartt@hpe.com' 4 | license 'All rights reserved' 5 | description 'Uses chef-provisioning-oneview' 6 | long_description 'Uses chef-provisioning-oneview' 7 | 8 | version '0.1.0' 9 | -------------------------------------------------------------------------------- /spec/support/fixtures/icsp/v102/error_404.json: -------------------------------------------------------------------------------- 1 | { 2 | "errorSource": null, 3 | "nestedErrors": [ 4 | 5 | ], 6 | "errorCode": "GENERIC_HTTP_404", 7 | "data": { 8 | }, 9 | "recommendedActions": [ 10 | "Check the request URI, then resend the request." 11 | ], 12 | "details": "The requested resource could not be found.", 13 | "message": "Not Found" 14 | } -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v120/error_404.json: -------------------------------------------------------------------------------- 1 | { 2 | "errorSource": null, 3 | "nestedErrors": [ 4 | 5 | ], 6 | "errorCode": "GENERIC_HTTP_404", 7 | "data": { 8 | }, 9 | "recommendedActions": [ 10 | "Check the request URI, then resend the request." 11 | ], 12 | "details": "The requested resource could not be found.", 13 | "message": "Not Found" 14 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | Berksfile.lock 8 | InstalledFiles 9 | _yardoc 10 | coverage 11 | doc/ 12 | lib/bundler/man 13 | pkg 14 | rdoc 15 | spec/reports 16 | test/tmp 17 | test/version_tmp 18 | tmp 19 | *.bundle 20 | *.so 21 | *.o 22 | *.a 23 | mkmf.log 24 | *.sw* 25 | destroy_all.rb 26 | machines.rb 27 | .kitchen/ 28 | -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v120/server-profiles_invalid_filter.json: -------------------------------------------------------------------------------- 1 | { 2 | "errorCode": "INVALID_FILTER", 3 | "data": { 4 | }, 5 | "details": "", 6 | "errorSource": null, 7 | "nestedErrors": [ 8 | 9 | ], 10 | "recommendedActions": [ 11 | "Verify parameters and try again." 12 | ], 13 | "message": "The specified filter is not valid ([serialNumber matches ''])." 14 | } -------------------------------------------------------------------------------- /examples/cookbooks/my_apache_server/metadata.rb: -------------------------------------------------------------------------------- 1 | name 'my_apache_server' 2 | maintainer 'Jared Smartt' 3 | maintainer_email 'jared.smartt@hp.com' 4 | license 'All rights reserved' 5 | description 'Installs/Configures my_apache_server' 6 | long_description 'Installs/Configures my_apache_server' 7 | 8 | version '0.1.1' 9 | 10 | supports 'centos' 11 | supports 'rhel' 12 | -------------------------------------------------------------------------------- /examples/cookbooks/my_apache_server/templates/default/index.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | HP Logo 4 |

Welcome!

5 |

This is a simple web page served by apache and managed by Chef

6 | Find more info about OneView here
7 | <%= node["ipaddress"] %>:<%= @port %> 8 | 9 | 10 | -------------------------------------------------------------------------------- /spec/support/fake_response.rb: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | # Helper for mocking responses 4 | class FakeResponse 5 | attr_reader :body, :code, :header 6 | 7 | def initialize(body = {}, code = 200, header = {}) 8 | @body = body 9 | @body = @body.to_json unless @body.class == String 10 | @code = code 11 | @header = header 12 | end 13 | 14 | def[](key) 15 | header[key] 16 | end 17 | 18 | def to_hash 19 | header 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/support/fixtures/icsp/v102/server_by_sn_empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "IndexPaginatedCollectionV4", 3 | "start": 0, 4 | "count": 0, 5 | "total": 1, 6 | "unFilteredTotal": 3, 7 | "uri": "/rest/index/resources?category=osdserver&count=50&start=0&query='osdServerSerialNumber:%22FAKESN%22'", 8 | "category": "resources", 9 | "members": [ 10 | ], 11 | "prevPageUri": null, 12 | "nextPageUri": null, 13 | "created": null, 14 | "modified": null, 15 | "eTag": null 16 | } -------------------------------------------------------------------------------- /examples/cookbooks/my_apache_server/README.md: -------------------------------------------------------------------------------- 1 | # my_apache_server-cookbook 2 | Basic Apache server 3 | 4 | ## Supported Platforms 5 | RHEL, CentOS 6 | 7 | ## Attributes 8 | TODO 9 | 10 | ## Usage 11 | 12 | ### my_apache_server::default 13 | 14 | Include `my_apache_server` in your node's `run_list`: 15 | 16 | ```json 17 | { 18 | "run_list": [ 19 | "recipe[my_apache_server::default]" 20 | ] 21 | } 22 | ``` 23 | 24 | ## License and Authors 25 | Author:: Jared Smartt (jsmartt) 26 | -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v120/server-profiles_name_empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "ServerProfileListV4", 3 | "members": [ 4 | ], 5 | "total": 0, 6 | "start": 0, 7 | "prevPageUri": null, 8 | "nextPageUri": null, 9 | "count": 0, 10 | "category": "server-profiles", 11 | "created": "20150810T223058.112Z", 12 | "eTag": "20150810T223058.112Z", 13 | "modified": "20150810T223058.112Z", 14 | "uri": "/rest/server-profiles?filter=name%20matches%20'FAKENAME'&sort=name:asc" 15 | } -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v120/server-profiles_sn_empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "ServerProfileListV4", 3 | "members": [ 4 | ], 5 | "total": 0, 6 | "start": 0, 7 | "prevPageUri": null, 8 | "nextPageUri": null, 9 | "count": 1, 10 | "category": "server-profiles", 11 | "created": "20150810T223058.112Z", 12 | "eTag": "20150810T223058.112Z", 13 | "modified": "20150810T223058.112Z", 14 | "uri": "/rest/server-profiles?filter=serialNumber%20matches%20'FAKESN'&sort=name:asc" 15 | } -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | require 'bundler/gem_tasks' 3 | require 'rspec/core/rake_task' 4 | require 'rubocop/rake_task' 5 | 6 | task default: :spec 7 | 8 | desc 'Run specs' 9 | RSpec::Core::RakeTask.new(:spec) do |spec| 10 | spec.pattern = 'spec/**/*_spec.rb' 11 | end 12 | 13 | RuboCop::RakeTask.new do |task| 14 | task.options << '--display-cop-names' 15 | end 16 | 17 | desc 'Runs rubocop and rspec' 18 | task :test do 19 | Rake::Task[:rubocop].invoke 20 | Rake::Task[:spec].invoke 21 | end 22 | -------------------------------------------------------------------------------- /spec/support/fake_machine_spec.rb: -------------------------------------------------------------------------------- 1 | module ChefProvisioningOneviewHelpers 2 | class FakeMachineSpec 3 | attr_reader :name 4 | attr_accessor :data 5 | 6 | def initialize(name, sn) 7 | @name = name 8 | @sn = sn 9 | @data = {} 10 | end 11 | 12 | def reference 13 | ver = Chef::Provisioning::ONEVIEW_DRIVER_VERSION 14 | { 15 | 'serial_number' => @sn, serial_number: @sn, 16 | 'driver_version' => ver, driver_version: ver 17 | } 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /examples/cookbooks/my_apache_server/templates/default/custom.erb: -------------------------------------------------------------------------------- 1 | <% if @port && @port != 80 -%> 2 | Listen <%= @port %> 3 | <% end -%> 4 | 5 | > 6 | ServerAdmin webmaster@localhost 7 | 8 | DocumentRoot <%= @document_root %> 9 | 10 | Options FollowSymLinks 11 | AllowOverride None 12 | 13 | > 14 | Options Indexes FollowSymLinks MultiViews 15 | AllowOverride None 16 | Order allow,deny 17 | allow from all 18 | 19 | 20 | -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v200/server-profile-templates_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "ServerProfileTemplateListV1", 3 | "members": [ 4 | 5 | ], 6 | "nextPageUri": null, 7 | "start": 0, 8 | "prevPageUri": null, 9 | "total": 0, 10 | "count": 0, 11 | "modified": "2015-09-15T23:22:13.939Z", 12 | "eTag": "2015-09-15T23:22:13.939Z", 13 | "created": "2015-09-15T23:22:13.939Z", 14 | "category": "server-profile-templates", 15 | "uri": "/rest/server-profile-templates?filter=%22name%20matches%20'INVALID'%22&sort=name:asc&start=0&count=64" 16 | } 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | © Copyright 2015 Hewlett Packard Enterprise Development LP 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9 | See the License for the specific language governing permissions and limitations under the License. 10 | -------------------------------------------------------------------------------- /examples/cookbooks/provisioning_cookbook/README.md: -------------------------------------------------------------------------------- 1 | # provisioning_cookbook-cookbook 2 | Example cookbook showing how easy it is to provision with OneView and Chef. 3 | 4 | ## Supported Platforms 5 | TODO 6 | 7 | ## Attributes 8 | 9 | TODO 10 | 11 | ## Usage 12 | TODO 13 | 14 | ### provisioning_cookbook::default 15 | Run `$ bundle exec chef-client -z recipes/default.rb` or... 16 | 17 | 18 | Include `provisioning_cookbook` in your node's `run_list`: 19 | 20 | ```json 21 | { 22 | "run_list": [ 23 | "recipe[provisioning_cookbook::default]" 24 | ] 25 | } 26 | ``` 27 | 28 | ## License and Authors 29 | Author:: Jared Smartt (jsmartt) 30 | -------------------------------------------------------------------------------- /examples/cookbooks/my_apache_server/spec/unit/recipes/default_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | # default recipe 4 | describe 'my_apache_server::default' do 5 | let(:chef_run) { ChefSpec::SoloRunner.new.converge(described_recipe) } 6 | 7 | it 'installs httpd' do 8 | expect(chef_run).to install_package('httpd') 9 | end 10 | 11 | it 'enables httpd' do 12 | expect(chef_run).to enable_service('httpd') 13 | end 14 | 15 | it 'creates the oneview app directory' do 16 | expect(chef_run).to create_directory('/var/www/oneview') 17 | end 18 | 19 | it 'deletes the default apache welcome page config file' do 20 | expect(chef_run).to delete_file('/etc/httpd/conf.d/welcome.conf') 21 | end 22 | 23 | end 24 | -------------------------------------------------------------------------------- /lib/chef/provisioning/helpers.rb: -------------------------------------------------------------------------------- 1 | require_relative 'create_machine' 2 | require_relative 'customize_machine' 3 | require_relative 'oneview/oneview_helper' 4 | require_relative 'oneview/san_storage' 5 | require_relative 'icsp/icsp_helper' 6 | 7 | module OneviewChefProvisioningDriver 8 | # Module that just includes all other helper modules 9 | module Helpers 10 | include CreateMachine # Handles allocation of OneView ServerProfile 11 | include CustomizeMachine # Handles OS install and network configuration 12 | 13 | include OneViewHelper # Helpers for OneView actions 14 | include OneViewSanStorage # Helpers for OneView SAN storage actions 15 | 16 | include IcspHelper # Helpers for ICSP actions 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /spec/unit/icsp_search_spec.rb: -------------------------------------------------------------------------------- 1 | require_relative './../spec_helper' 2 | 3 | RSpec.describe Chef::Provisioning::OneViewDriver do 4 | include_context 'shared context' 5 | 6 | describe '#get_icsp_server_by_sn' do 7 | it 'gets info for a valid SN' do 8 | ret_val = @driver_120.instance_eval { get_icsp_server_by_sn('VCGE9KB041') } 9 | expect(ret_val['serialNumber']).to eq('VCGE9KB041') 10 | expect(ret_val['uri']).to match(%r{\/rest\/os-deployment-servers\/.+}) 11 | end 12 | 13 | it 'returns nil for fake SN' do 14 | ret_val = @driver_120.instance_eval { get_icsp_server_by_sn('FAKESN') } 15 | expect(ret_val).to be_nil 16 | end 17 | 18 | it 'fails when an empty SN is given' do 19 | expect { @driver_120.instance_eval { get_icsp_server_by_sn('') } }.to raise_error('Must specify a serialNumber!') 20 | end 21 | 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /examples/cookbooks/my_apache_server/recipes/default.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: my_apache_server 3 | # Recipe:: default 4 | # 5 | # Copyright (C) 2015 HP 6 | # 7 | # All rights reserved - Do Not Redistribute 8 | # 9 | 10 | package 'httpd' do 11 | action :install 12 | end 13 | 14 | file '/etc/httpd/conf.d/welcome.conf' do 15 | action :delete 16 | notifies :restart, 'service[httpd]', :delayed 17 | end 18 | 19 | document_root = '/var/www/oneview' 20 | template '/etc/httpd/conf.d/oneview.conf' do 21 | source 'custom.erb' 22 | mode '0644' 23 | variables( 24 | :document_root => document_root, 25 | :port => 80 26 | ) 27 | end 28 | 29 | directory document_root do 30 | mode '0755' 31 | recursive true 32 | end 33 | 34 | remote_directory document_root do 35 | files_mode '0755' 36 | source 'oneview' 37 | notifies :restart, 'service[httpd]', :delayed 38 | sensitive true 39 | end 40 | 41 | service 'httpd' do 42 | action [ :enable, :start ] 43 | end 44 | -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v120/storage-volumes_1B5D3CA2-6C5B-41C2-8B97-1821F1883F22.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "StorageVolumeV2", 3 | "deviceType": "FC", 4 | "wwn": "50:00:2A:C0:02:B0:15:9F", 5 | "raidLevel": "RAID5", 6 | "storageSystemUri": "/rest/storage-systems/1405534", 7 | "storagePoolUri": "/rest/storage-pools/707E383B-56F6-48A1-BFF1-782BB2AC6BA7", 8 | "isPermanent": false, 9 | "provisionType": "Thin", 10 | "shareable": false, 11 | "provisionedCapacity": "53687091200", 12 | "deviceVolumeName": "bootVol", 13 | "allocatedCapacity": "671088640", 14 | "revertToSnapshotUri": null, 15 | "refreshState": "NotRefreshing", 16 | "stateReason": "None", 17 | "description": null, 18 | "status": "OK", 19 | "name": "bootVol", 20 | "state": "Normal", 21 | "eTag": "2015-10-16T20:20:06.364Z", 22 | "created": "2015-10-16T20:19:36.526Z", 23 | "modified": null, 24 | "category": "storage-volumes", 25 | "uri": "/rest/storage-volumes/1B5D3CA2-6C5B-41C2-8B97-1821F1883F22" 26 | } 27 | -------------------------------------------------------------------------------- /examples/cookbooks/my_apache_server/chefignore: -------------------------------------------------------------------------------- 1 | # Put files/directories that should be ignored in this file when uploading 2 | # or sharing to the community site. 3 | # Lines that start with '# ' are comments. 4 | 5 | # OS generated files # 6 | ###################### 7 | .DS_Store 8 | Icon? 9 | nohup.out 10 | ehthumbs.db 11 | Thumbs.db 12 | 13 | # SASS # 14 | ######## 15 | .sass-cache 16 | 17 | # EDITORS # 18 | ########### 19 | \#* 20 | .#* 21 | *~ 22 | *.sw[a-z] 23 | *.bak 24 | REVISION 25 | TAGS* 26 | tmtags 27 | *_flymake.* 28 | *_flymake 29 | *.tmproj 30 | .project 31 | .settings 32 | mkmf.log 33 | 34 | ## COMPILED ## 35 | ############## 36 | a.out 37 | *.o 38 | *.pyc 39 | *.so 40 | *.com 41 | *.class 42 | *.dll 43 | *.exe 44 | */rdoc/ 45 | 46 | # Testing # 47 | ########### 48 | .watchr 49 | .rspec 50 | spec/* 51 | spec/fixtures/* 52 | test/* 53 | features/* 54 | Guardfile 55 | Procfile 56 | 57 | # SCM # 58 | ####### 59 | .git 60 | */.git 61 | .gitignore 62 | .gitmodules 63 | .gitconfig 64 | .gitattributes 65 | .svn 66 | */.bzr/* 67 | */.hg/* 68 | */.svn/* 69 | 70 | # Berkshelf # 71 | ############# 72 | cookbooks/* 73 | tmp 74 | 75 | # Cookbooks # 76 | ############# 77 | CONTRIBUTING 78 | CHANGELOG* 79 | 80 | # Strainer # 81 | ############ 82 | Colanderfile 83 | Strainerfile 84 | .colander 85 | .strainer 86 | 87 | # Vagrant # 88 | ########### 89 | .vagrant 90 | Vagrantfile 91 | 92 | # Travis # 93 | ########## 94 | .travis.yml 95 | -------------------------------------------------------------------------------- /examples/cookbooks/provisioning_cookbook/chefignore: -------------------------------------------------------------------------------- 1 | # Put files/directories that should be ignored in this file when uploading 2 | # or sharing to the community site. 3 | # Lines that start with '# ' are comments. 4 | 5 | # OS generated files # 6 | ###################### 7 | .DS_Store 8 | Icon? 9 | nohup.out 10 | ehthumbs.db 11 | Thumbs.db 12 | 13 | # SASS # 14 | ######## 15 | .sass-cache 16 | 17 | # EDITORS # 18 | ########### 19 | \#* 20 | .#* 21 | *~ 22 | *.sw[a-z] 23 | *.bak 24 | REVISION 25 | TAGS* 26 | tmtags 27 | *_flymake.* 28 | *_flymake 29 | *.tmproj 30 | .project 31 | .settings 32 | mkmf.log 33 | 34 | ## COMPILED ## 35 | ############## 36 | a.out 37 | *.o 38 | *.pyc 39 | *.so 40 | *.com 41 | *.class 42 | *.dll 43 | *.exe 44 | */rdoc/ 45 | 46 | # Testing # 47 | ########### 48 | .watchr 49 | .rspec 50 | spec/* 51 | spec/fixtures/* 52 | test/* 53 | features/* 54 | Guardfile 55 | Procfile 56 | 57 | # SCM # 58 | ####### 59 | .git 60 | */.git 61 | .gitignore 62 | .gitmodules 63 | .gitconfig 64 | .gitattributes 65 | .svn 66 | */.bzr/* 67 | */.hg/* 68 | */.svn/* 69 | 70 | # Berkshelf # 71 | ############# 72 | cookbooks/* 73 | tmp 74 | 75 | # Cookbooks # 76 | ############# 77 | CONTRIBUTING 78 | CHANGELOG* 79 | 80 | # Strainer # 81 | ############ 82 | Colanderfile 83 | Strainerfile 84 | .colander 85 | .strainer 86 | 87 | # Vagrant # 88 | ########### 89 | .vagrant 90 | Vagrantfile 91 | 92 | # Travis # 93 | ########## 94 | .travis.yml 95 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | # See default at https://github.com/bbatsov/rubocop/blob/master/config/default.yml 2 | 3 | 4 | # Common configuration. 5 | AllCops: 6 | Exclude: 7 | - 'examples/cookbooks/**/*' 8 | 9 | 10 | # Modified Cops: 11 | Metrics/ClassLength: 12 | Max: 200 13 | 14 | Metrics/MethodLength: 15 | Max: 50 16 | 17 | Metrics/LineLength: # TODO: Lower to 150 18 | Max: 210 19 | 20 | Style/IndentationWidth: 21 | Width: 2 22 | 23 | Style/VariableName: 24 | EnforcedStyle: snake_case 25 | 26 | Style/AlignParameters: 27 | EnforcedStyle: with_fixed_indentation 28 | 29 | Style/EmptyLinesAroundBlockBody: 30 | EnforcedStyle: no_empty_lines 31 | Exclude: 32 | - 'spec/**/*' 33 | 34 | Style/GlobalVars: 35 | AllowedVariables: [ 36 | $server_created # For Spec testing: (required to allow 2 different responses when searching for a server profile) 37 | ] 38 | 39 | 40 | # Disabled Cops: 41 | Metrics/AbcSize: 42 | Enabled: false 43 | 44 | Metrics/CyclomaticComplexity: 45 | Enabled: false 46 | 47 | Style/AccessorMethodName: 48 | Enabled: false 49 | 50 | Style/ClassAndModuleChildren: 51 | Enabled: false 52 | 53 | Style/EmptyLines: 54 | Enabled: false 55 | 56 | Style/EmptyLinesAroundClassBody: 57 | Enabled: false 58 | 59 | Style/GuardClause: # TODO: Re-enable at some point 60 | Enabled: false 61 | 62 | Metrics/PerceivedComplexity: 63 | Enabled: false 64 | 65 | Lint/RescueException: 66 | Enabled: false 67 | 68 | Style/RescueModifier: 69 | Enabled: false 70 | 71 | Metrics/ModuleLength: 72 | Enabled: false 73 | -------------------------------------------------------------------------------- /spec/support/fixtures/icsp/v102/server_by_sn_VCGE9KB041.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "IndexPaginatedCollectionV4", 3 | "start": 0, 4 | "count": 1, 5 | "total": 1, 6 | "unFilteredTotal": 3, 7 | "uri": "/rest/index/resources?category=osdserver&count=50&start=0&query='osdServerSerialNumber:%22VCGE9KB041%22'", 8 | "category": "resources", 9 | "members": [ 10 | { 11 | "type": "IndexResource", 12 | "multiAttributes": { 13 | }, 14 | "ownerId": "OsdServerIndex", 15 | "eTag": "2015-08-10T04:55:27.017Z", 16 | "attributes": { 17 | "osdServerRack": "DemoRack", 18 | "osdServerStage": "UNKNOWN", 19 | "osdServerSerialNumber": "VCGE9KB041", 20 | "osdServerIPAddress": "192.168.133.36", 21 | "osdServerLifeCycle": "MANAGED", 22 | "osdServerId": "1670001", 23 | "osdServerRunning": "false", 24 | "osdServerState": "OK", 25 | "osdServerBay": "2", 26 | "osdServerEnclosure": "dazzle", 27 | "osdServerModel": "PROLIANT BL460C GEN8", 28 | "osdServerHostName": "chef-web02.domain.com" 29 | }, 30 | "description": null, 31 | "name": "chef-web01.domain.com", 32 | "state": null, 33 | "status": "OK", 34 | "created": "2015-08-10T04:35:40.000Z", 35 | "modified": "2015-08-10T16:45:57.019Z", 36 | "category": "osdserver", 37 | "uri": "/rest/os-deployment-servers/1670001" 38 | } 39 | ], 40 | "prevPageUri": null, 41 | "nextPageUri": null, 42 | "created": null, 43 | "modified": null, 44 | "eTag": null 45 | } -------------------------------------------------------------------------------- /chef-provisioning-oneview.gemspec: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift(File.dirname(__FILE__) + '/lib') 2 | require 'chef/provisioning/version' 3 | 4 | Gem::Specification.new do |s| 5 | s.name = 'chef-provisioning-oneview' 6 | s.version = Chef::Provisioning::ONEVIEW_DRIVER_VERSION 7 | s.platform = Gem::Platform::RUBY 8 | s.extra_rdoc_files = ['README.md', 'LICENSE'] 9 | s.summary = 'Chef Provisioning driver for OneView' 10 | s.description = 'Chef Provisioning driver for creating and managing OneView infrastructure.' 11 | s.author = 'Hewlett Packard Enterprise' 12 | s.email = ['jared.smartt@hpe.com', 'gunjan.kamle@hpe.com'] 13 | s.homepage = 'https://github.com/HewlettPackard/chef-provisioning-oneview' 14 | s.license = 'Apache-2.0' 15 | 16 | case RUBY_VERSION 17 | when /^2\.0/ 18 | s.add_dependency 'chef', '~> 12.0', '< 12.9' 19 | when /^2\.(1|2\.[01])/ 20 | s.add_dependency 'chef', '~> 12.0', '< 12.14' 21 | else 22 | s.add_dependency 'chef', '~> 12.0' 23 | end 24 | s.add_dependency 'oneview-sdk', '~> 2.1' 25 | s.add_dependency 'chef-provisioning', '~> 1.0' 26 | 27 | s.add_development_dependency 'rspec', '~> 3.0' 28 | s.add_development_dependency 'rake' 29 | s.add_development_dependency 'sinatra' 30 | s.add_development_dependency 'webmock' 31 | s.add_development_dependency 'simplecov' 32 | s.add_development_dependency 'rubocop', '= 0.40.0' 33 | s.add_development_dependency 'pry' 34 | 35 | s.require_path = 'lib' 36 | 37 | all_files = `git ls-files -z`.split("\x0") 38 | s.files = Dir['LICENSE', 'README.md', '*.gemspec', 'lib/**/*'].reject { |f| !all_files.include?(f) } 39 | end 40 | -------------------------------------------------------------------------------- /lib/chef/provisioning/icsp/api_v104.rb: -------------------------------------------------------------------------------- 1 | # Helper module for ICSP v104 API requests 2 | module ICspAPIv104 3 | # Parse and clean connection data for api call 4 | def icsp_v104_parse_connection(machine_options, c) 5 | allowed_keys = %w(macAddress enabled dhcpv4 ipv6autoconfig provisioning dnsServers winsServers dnsSearch staticNetworks vlanid ipv4gateway ipv6gateway) 6 | c[:enabled] ||= true 7 | c[:vlanid] ||= '-1' 8 | c[:dhcpv4] ||= c[:dhcp] 9 | c[:ipv4gateway] ||= c[:gateway] || machine_options[:driver_options][:gateway] 10 | c[:ipv4gateway] = nil if c[:ipv4gateway] == :none 11 | c[:dnsServers] ||= c[:dns] || machine_options[:driver_options][:dns] || [] 12 | c[:dnsServers] = nil if c[:dnsServers] == :none 13 | c[:dnsServers] = c[:dnsServers].split(',') if c[:dnsServers].class == String 14 | c[:staticNetworks] ||= ["#{c[:ip4Address]}/#{c[:mask] || machine_options[:driver_options][:mask] || '24'}"] if c[:ip4Address] 15 | c.keep_if { |k, _v| allowed_keys.include? k.to_s } 16 | end 17 | 18 | # Parse and clean personality_data data for api call 19 | def icsp_v104_build_personality_data(machine_options, nics) 20 | allowed_keys = %w(hostname domain workgroup) 21 | personality_data = Marshal.load(Marshal.dump(machine_options[:driver_options])) || {} 22 | personality_data.keep_if { |k, _v| allowed_keys.include? k.to_s } 23 | personality_data['hostname'] ||= machine_options[:driver_options][:host_name] 24 | personality_data['domain'] ||= machine_options[:driver_options][:domainName] 25 | personality_data['interfaces'] = nics 26 | personality_data 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'pry' 2 | require 'webmock/rspec' 3 | require 'simplecov' 4 | SimpleCov.start 5 | 6 | require_relative './../lib/chef/provisioning/driver_init/oneview' 7 | require_relative 'support/fake_response' 8 | require_relative 'support/fake_oneview' 9 | require_relative 'support/fake_icsp' 10 | require_relative 'support/fake_machine_spec' 11 | require_relative 'support/fake_action_handler' 12 | require_relative 'shared_context' 13 | # WebMock.disable_net_connect!(allow_localhost: true) 14 | 15 | RSpec.configure do |config| 16 | config.before(:each) do 17 | stub_request(:any, /my-oneview.my-domain.com/).to_rack(FakeOneView) 18 | stub_request(:any, /my-icsp.my-domain.com/).to_rack(FakeIcsp) 19 | 20 | @oneview_url = 'https://oneview.example.com' 21 | @oneview_user = 'Administrator' 22 | @oneview_password = 'secret123' 23 | @oneview_token = 'A954A2A6Psy7Alg3HApAcEbAcAwa-ftA' 24 | 25 | @icsp_url = 'https://icsp.example.com' 26 | @icsp_user = 'admin' 27 | @icsp_password = 'secret456' 28 | @icsp_key = 'AA_aaAaa3AA3Aa0_aAaAA4AAAA3AAAAA' 29 | 30 | @canonical_url = "oneview:#{@oneview_url}" 31 | 32 | stub_request(:any, /icsp.example.com/).to_rack(FakeIcsp) 33 | 34 | allow_any_instance_of(OneviewSDK::Client).to receive(:appliance_api_version).and_return(200) 35 | allow_any_instance_of(OneviewSDK::Client).to receive(:login).and_return(@oneview_token) 36 | allow(OneviewSDK::SSLHelper).to receive(:load_trusted_certs).and_return(nil) 37 | 38 | # Clear environment variables 39 | %w(ONEVIEWSDK_URL ONEVIEWSDK_USER ONEVIEWSDK_PASSWORD ONEVIEWSDK_TOKEN ONEVIEWSDK_SSL_ENABLED).each do |name| 40 | ENV[name] = nil 41 | end 42 | end 43 | 44 | end 45 | 46 | # Chef::Log.level = :debug 47 | Chef::Config[:log_level] = :warn 48 | -------------------------------------------------------------------------------- /lib/chef/provisioning/icsp/rest.rb: -------------------------------------------------------------------------------- 1 | module OneviewChefProvisioningDriver 2 | # Helpers for REST API calls 3 | module RestAPI 4 | # API calls for OneView and ICsp 5 | def rest_api(host, type, path, options = {}) 6 | disable_ssl = false 7 | case host 8 | when 'icsp', :icsp 9 | uri = URI.parse(URI.escape(@icsp_base_url + path)) 10 | options['X-API-Version'] ||= @icsp_api_version unless [:put, 'put'].include?(type.downcase) 11 | options['auth'] ||= @icsp_key 12 | disable_ssl = true if @icsp_disable_ssl 13 | else 14 | raise "Invalid rest host: #{host}" 15 | end 16 | 17 | http = Net::HTTP.new(uri.host, uri.port) 18 | http.read_timeout = @icsp_timeout if @icsp_timeout # timeout for a request 19 | http.open_timeout = @icsp_timeout if @icsp_timeout # timeout for a connection 20 | http.use_ssl = true if uri.scheme == 'https' 21 | http.verify_mode = OpenSSL::SSL::VERIFY_NONE if disable_ssl 22 | case type.downcase 23 | when 'get', :get 24 | request = Net::HTTP::Get.new(uri.request_uri) 25 | when 'post', :post 26 | request = Net::HTTP::Post.new(uri.request_uri) 27 | when 'put', :put 28 | request = Net::HTTP::Put.new(uri.request_uri) 29 | when 'delete', :delete 30 | request = Net::HTTP::Delete.new(uri.request_uri) 31 | else 32 | raise "Invalid rest call: #{type}" 33 | end 34 | options['Content-Type'] ||= 'application/json' 35 | options.delete('Content-Type') if [:none, 'none', nil].include?(options['Content-Type']) 36 | options.delete('X-API-Version') if [:none, 'none', nil].include?(options['X-API-Version']) 37 | options.delete('auth') if [:none, 'none', nil].include?(options['auth']) 38 | options.each do |key, val| 39 | if key.casecmp('body') == 0 40 | request.body = val.to_json rescue val 41 | else 42 | request[key] = val 43 | end 44 | end 45 | 46 | response = http.request(request) 47 | JSON.parse(response.body) rescue response 48 | end 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /examples/ssl_issues.md: -------------------------------------------------------------------------------- 1 | #SSL: Trusting The Chef Server's Invalid Certs (for Ruby libraries like Net::SSH and Ridley) 2 | 3 | ###On Windows (requires git bash & it's linux tools): 4 | Either: 5 | 6 | 1. Run the [install_ssl_certs.rb](install_ssl_certs.rb) script 7 | ```bash 8 | ruby install_ssl_certs.rb 9 | ``` 10 | 11 | 2. Run the commands manually 12 | ```bash 13 | # Download and convert the cert: 14 | SERVER="MY_SERVER.DOMAIN.com" 15 | openssl s_client -connect $SERVER:443 | tee /C/opscode/chefdk/embedded/ssl/certs/$SERVER.crt 16 | openssl x509 -in /C/opscode/chefdk/embedded/ssl/certs/$SERVER.crt -out /C/opscode/chefdk/embedded/ssl/certs/$SERVER.pem -outform PEM 17 | 18 | # To add it to Ruby's trusted store: 19 | echo -e "\nChef Server at $SERVER\n=========================================" >> /C/opscode/chefdk/embedded/ssl/certs/cacert.pem 20 | cat /C/opscode/chefdk/embedded/ssl/certs/$SERVER.pem >> /C/opscode/chefdk/embedded/ssl/certs/cacert.pem 21 | ``` 22 | 23 | 24 | ###On RHEL Systems: 25 | Either: 26 | 27 | 1. Run the [install_ssl_certs.rb](install_ssl_certs.rb) script. As root... 28 | ```bash 29 | ruby install_ssl_certs.rb 30 | ``` 31 | 32 | 2. Run the commands manually. As root... 33 | ```bash 34 | # as root... 35 | # Download and convert the cert: 36 | SERVER="MY_SERVER.DOMAIN.com" 37 | openssl s_client -showcerts -connect $SERVER:443 /dev/null | tee /etc/pki/tls/certs/$SERVER.crt 38 | openssl x509 -in /etc/pki/tls/certs/$SERVER.crt -out /etc/pki/ca-trust/source/anchors/$SERVER.pem -outform PEM 39 | 40 | # To add it to Ruby's trusted store: 41 | gem which rubygems # Should return /opt/chefdk/embedded/lib/ruby/site_ruby/2.1.0/rubygems.rb 42 | echo -e "\nChef Server at $SERVER\n=========================================" >> /opt/chefdk/embedded/ssl/certs/cacert.pem 43 | cat /etc/pki/ca-trust/source/anchors/$SERVER.pem >> /opt/chefdk/embedded/ssl/certs/cacert.pem 44 | 45 | # To also trust it for the rest of the OS (ie curl, etc.): 46 | # Note: Depends on the 2 openssl commands above being run already. It looks for & adds .pem files in /etc/pki/ca-trust/source/anchors/ 47 | update-ca-trust force-enable 48 | update-ca-trust 49 | curl -I https://$SERVER # Should not give SSL error 50 | ``` 51 | -------------------------------------------------------------------------------- /spec/unit/icsp_helper_spec.rb: -------------------------------------------------------------------------------- 1 | require_relative './../spec_helper' 2 | 3 | RSpec.describe Chef::Provisioning::OneViewDriver do 4 | include_context 'shared context' 5 | 6 | let(:profile_120) do 7 | 'spec/support/fixtures/oneview/v120/server_profile_web01_with_san.json' 8 | end 9 | 10 | describe '#destroy_icsp_server' do 11 | it 'destroys the server' do 12 | a = action_handler 13 | m = machine_spec 14 | @driver_120.instance_eval { destroy_icsp_server(a, m) } 15 | expect(a_request(:delete, %r{/rest/os-deployment-servers/.*})).to have_been_made 16 | end 17 | end 18 | 19 | describe '#icsp_configure_nic_teams' do 20 | it 'configures nic teams properly' do 21 | machine_options = valid_machine_options 22 | profile = OneviewSDK::ServerProfile.from_file(@ov_200, profile_120) 23 | ret_val = @driver_120.instance_eval { icsp_configure_nic_teams(machine_options, profile) } 24 | expect(ret_val).to eq('team1-11:11:11:11:01:14,11:11:11:11:01:15') 25 | end 26 | 27 | it 'requires connection IDs to map to valid OneView connection IDs' do 28 | machine_options = valid_machine_options 29 | profile = OneviewSDK::ServerProfile.from_file(@ov_200, profile_120) 30 | machine_options[:driver_options][:connections][99] = { team: 'team2' } 31 | expect { @driver_120.instance_eval { icsp_configure_nic_teams(machine_options, profile) } }.to raise_error(/make sure the connection ids map to those on OneView/) 32 | end 33 | 34 | it 'does not allow nic teams with hyphens' do 35 | machine_options = valid_machine_options 36 | profile = OneviewSDK::ServerProfile.from_file(@ov_200, profile_120) 37 | machine_options[:driver_options][:connections][1][:team] = 'team-1' 38 | expect { @driver_120.instance_eval { icsp_configure_nic_teams(machine_options, profile) } }.to raise_error(/must not include hyphens/) 39 | end 40 | 41 | it 'requires at least 2 connections per team' do 42 | machine_options = valid_machine_options 43 | profile = OneviewSDK::ServerProfile.from_file(@ov_200, profile_120) 44 | machine_options[:driver_options][:connections].delete(2) 45 | expect { @driver_120.instance_eval { icsp_configure_nic_teams(machine_options, profile) } }.to raise_error(/must have at least 2 associated connections/) 46 | end 47 | 48 | end 49 | 50 | end 51 | -------------------------------------------------------------------------------- /spec/support/fixtures/icsp/v102/os-deployment-servers_1670001.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "OSDServer", 3 | "modified": "2015-08-10T04:55:27.017Z", 4 | "deviceGroups": null, 5 | "customAttributes": [], 6 | "created": "2015-08-10T04:35:40.000Z", 7 | "uuid": "7d805e1c-beac-e84e-868b-2fb0b6504474", 8 | "cpus": [ 9 | { 10 | "cacheSize": "15360", 11 | "speed": "1200", 12 | "stepping": "7", 13 | "model": "Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00GHz", 14 | "family": "X64", 15 | "status": "ON-LINE", 16 | "slot": "0" 17 | } 18 | ], 19 | "ilo": null, 20 | "serverLocation": { 21 | "rack": "DemoRack", 22 | "enclosure": "dazzle", 23 | "bay": "2" 24 | }, 25 | "operatingSystemVersion": null, 26 | "opswLifecycle": "MANAGED", 27 | "osSPVersion": null, 28 | "peerIP": "192.168.133.36", 29 | "stage": "UNKNOWN", 30 | "running": "false", 31 | "reporting": true, 32 | "storageDevices": [], 33 | "ram": "16291780", 34 | "swap": "8216568", 35 | "architecture": null, 36 | "defaultGateway": "172.125.32.1", 37 | "discoveredDate": "2015-08-10T04:35:39.000Z", 38 | "facility": "Appliance", 39 | "hardwareModel": "PROLIANT BL460C GEN8", 40 | "jobsHistory": null, 41 | "lastScannedDate": null, 42 | "loopbackIP": null, 43 | "managementIP": "192.168.133.36", 44 | "manufacturer": "HP", 45 | "mid": "1670001", 46 | "netBios": null, 47 | "operatingSystem": null, 48 | "osFlavor": null, 49 | "serialNumber": "VCGE9KB041", 50 | "locale": null, 51 | "description": null, 52 | "status": "OK", 53 | "uri": "/rest/os-deployment-servers/1670001", 54 | "name": "chef-web01.domain.com", 55 | "interfaces": [ 56 | { 57 | "speed": "10000", 58 | "netmask": "255.255.254.0", 59 | "duplex": "FULL", 60 | "ipv6Addr": "", 61 | "macAddr": "11:11:11:11:01:15", 62 | "dhcpEnabled": false, 63 | "ipv4Addr": "172.125.32.38", 64 | "type": "ETHERNET", 65 | "slot": "eth1" 66 | }, 67 | { 68 | "speed": "10000", 69 | "netmask": "255.255.255.0", 70 | "duplex": "FULL", 71 | "ipv6Addr": "", 72 | "macAddr": "11:11:11:11:01:14", 73 | "dhcpEnabled": true, 74 | "ipv4Addr": "192.168.133.36", 75 | "type": "ETHERNET", 76 | "slot": "eth0" 77 | } 78 | ], 79 | "state": "OK", 80 | "hostName": "chef-web01.domain.com", 81 | "eTag": "2015-08-10T04:55:27.017Z", 82 | "category": "os-deployment-servers" 83 | } -------------------------------------------------------------------------------- /lib/chef/provisioning/create_machine.rb: -------------------------------------------------------------------------------- 1 | module OneviewChefProvisioningDriver 2 | # Handles allocation of OneView ServerProfile 3 | module CreateMachine 4 | # Allocate OneView server profile 5 | def create_machine(action_handler, machine_name, machine_options) 6 | host_name = machine_options[:driver_options][:host_name] || machine_name 7 | profile_name = machine_options[:driver_options][:profile_name] || host_name 8 | 9 | # Check if profile exists first 10 | matching_profile = OneviewSDK::ServerProfile.find_by(@ov, name: host_name).first 11 | return matching_profile if matching_profile 12 | 13 | # Search for OneView Template or Profile by name 14 | template_name = machine_options[:driver_options][:server_template] 15 | profile = profile_from_template(template_name, profile_name) 16 | 17 | # Get first availabe (and compatible) OneView server blade. 18 | # If a server_location has been specified, uses that 19 | hw = available_hardware_for_profile(profile, machine_options[:driver_options][:server_location]) 20 | 21 | action_handler.perform_action "Power off server #{hw['name']} for machine '#{machine_name}'" do 22 | action_handler.report_progress "INFO: Powering off server #{hw['name']} for machine '#{machine_name}'" 23 | hw.power_off 24 | end 25 | 26 | # Create new ServerProfile from the template 27 | action_handler.perform_action "Create server profile for #{machine_name}" do 28 | action_handler.report_progress "INFO: Creating server profile for #{machine_name}" 29 | profile.set_server_hardware(hw) 30 | update_san_info(machine_name, profile) 31 | response = @ov.rest_post(profile.class::BASE_URI, { 'body' => profile.data }, profile.api_version) 32 | unless response.code.to_i == 202 33 | task = JSON.parse(response.body) 34 | raise "Server profile couldn't be created! #{task['taskStatus']}. #{task['taskErrors'].first['message'] rescue nil}" 35 | end 36 | 60.times do # Wait for up to 5 min for profile to appear in OneView 37 | return profile if profile.retrieve! 38 | task = @ov.response_handler(@ov.rest_get(response.header['location'] || JSON.parse(response.body)['uri'])) 39 | break if task['taskState'] == 'Error' 40 | print '.' 41 | sleep 5 42 | end 43 | raise "Server profile couldn't be created! #{task['taskStatus']}. #{task['taskErrors'].first['message'] rescue nil}" 44 | end 45 | profile 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /examples/install_ssl_certs.rb: -------------------------------------------------------------------------------- 1 | require 'net/http' 2 | require 'ridley' 3 | 4 | script_dir = File.expand_path File.dirname(__FILE__) 5 | 6 | def ssl_verify(url, cert_file = ENV['SSL_CERT_FILE']) 7 | uri = URI.parse(url) 8 | Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https', ca_file: cert_file) do |_http| 9 | return true 10 | end 11 | rescue OpenSSL::SSL::SSLError 12 | return nil 13 | end 14 | 15 | def install_cert(url, cert_file = ENV['SSL_CERT_FILE'], name = 'Chef Server') 16 | uri = URI.parse(url) 17 | pem = Net::HTTP.start(uri.host, uri.port, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE) do |http| 18 | http.peer_cert.to_pem 19 | end 20 | 21 | raise "Could not download cert from #{url}. You may have to do it manually, and append it to '#{cert_file}'" if pem.nil? 22 | 23 | print " Writing #{uri.host} cert to '#{cert_file}'..." 24 | open(cert_file, 'ab') do |f| 25 | s = "\n#{name} at #{uri.host}" 26 | f.write "#{s}\n" 27 | f.write "#{'=' * (s.length - 1)}\n" 28 | f.write pem 29 | end 30 | puts " Done! \n" 31 | end 32 | 33 | knife_location = File.expand_path("#{script_dir}/.chef/knife.rb") 34 | raise "Error! knife.rb file not found at '#{knife_location}'!" unless File.exist?(knife_location) 35 | config = Ridley::Chef::Config.new(knife_location).to_hash 36 | chef_server_url = config[:chef_server_url] 37 | chef_server_url.sub! ':443', '' if chef_server_url 38 | supermarket_site = config[:knife][:supermarket_site] rescue nil 39 | 40 | 41 | puts "============================Adding certs to system keystores============================\n" 42 | keystores = [] 43 | keystores.push ENV['SSL_CERT_FILE'] if ENV['SSL_CERT_FILE'] 44 | [ 45 | 'c:/Program Files (x86)/Git/bin/curl-ca-bundle.crt', 46 | 'c:/opscode/chefdk/embedded/ssl/certs/cacert.pem', 47 | '/opt/chefdk/embedded/ssl/certs/cacert.pem' 48 | ].each do |ca_bundle| 49 | keystores.push(ca_bundle) if File.exist?(ca_bundle) && !keystores.include?(ca_bundle) 50 | end 51 | 52 | keystores.each do |keystore| 53 | puts "\nKeystore #{keystore}" 54 | 55 | if ssl_verify(chef_server_url, keystore) 56 | puts " #{URI.parse(chef_server_url).host}: Nothing to do" 57 | else 58 | install_cert(chef_server_url, keystore) 59 | end 60 | 61 | next unless supermarket_site 62 | if ssl_verify(supermarket_site, keystore) 63 | puts " #{URI.parse(supermarket_site).host}: Nothing to do" 64 | else 65 | install_cert(supermarket_site, keystore, 'Chef Private Supermarket') 66 | end 67 | end 68 | 69 | puts "\n\n============================Adding cert(s) to knife's trusted list============================\n\n" 70 | system "knife ssl fetch #{chef_server_url}" 71 | system "knife ssl fetch #{supermarket_site}" if supermarket_site 72 | -------------------------------------------------------------------------------- /lib/chef/provisioning/oneview/oneview_helper.rb: -------------------------------------------------------------------------------- 1 | module OneviewChefProvisioningDriver 2 | # Helpers for OneView actions 3 | module OneViewHelper 4 | # Create new Profile from template or server profile 5 | # @return [OneviewSDK::ServerProfile] server profile 6 | def profile_from_template(template_name, profile_name) 7 | raise 'Template name missing! Please set machine_options[:driver_options][:server_template]' unless template_name 8 | if @ov.api_version >= 200 9 | # Look for Server Profile Template (OneView 2.0 or higher) 10 | template = OneviewSDK::ServerProfileTemplate.find_by(@ov, name: template_name).first 11 | return template.new_profile(profile_name) if template 12 | end 13 | 14 | # Look for Server Profile as second option 15 | profile = OneviewSDK::ServerProfile.find_by(@ov, name: template_name).first 16 | raise "Template '#{template_name}' not found! Please match the template name with one that exists on OneView." unless profile 17 | profile['name'] = profile_name 18 | 19 | # Remove unwanted fields 20 | %w(uri serialNumber uuid taskUri enclosureBay enclosureUri).each { |key| profile.data.delete(key) } 21 | profile['connections'].each do |c| 22 | %w(wwnn wwpn mac deploymentStatus interconnectUri wwpnType macType).each { |key| c[key] = nil } 23 | end 24 | profile 25 | end 26 | 27 | # Get an available hardware for a template. If a specific location is requested, find it 28 | # @return [OneviewSDK::ServerHardware] 29 | def available_hardware_for_profile(profile, location = nil) 30 | Chef::Log.debug "Specific hardware requested: #{location}" if location 31 | hw_list = profile.get_available_hardware 32 | raise 'Error! No available blades that are compatible with the server template!' if hw_list.empty? 33 | if location 34 | chosen_blade = hw_list.find { |h| h['name'] == location } 35 | return chosen_blade if chosen_blade 36 | raise "Specified hardware '#{location}' doesn't exist or doesn't match the given template" 37 | end 38 | hw_list.first # If no location is specified, return the first matching HW 39 | end 40 | 41 | # Wait for the profile to finish being applied 42 | # @return [TrueClass, FalseClass] 43 | def wait_for_profile(action_handler, machine_name, profile) 44 | return true if profile['state'] == 'Normal' 45 | action_handler.perform_action "Apply profile '#{profile['name']}' for machine '#{machine_name}'" do 46 | action_handler.report_progress "INFO: Applying profile '#{profile['name']}' for machine '#{machine_name}'" 47 | @ov.wait_for(profile['taskUri']) 48 | end 49 | profile.refresh 50 | raise "Server profile state '#{profile['state']}' not 'Normal'" unless profile['state'] == 'Normal' 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /examples/.chef/knife.rb.example: -------------------------------------------------------------------------------- 1 | # See http://docs.chef.io/config_rb_knife.html for more information on knife configuration options 2 | current_dir = File.dirname(__FILE__) 3 | 4 | #============================================================================= 5 | # Edit these attributes: 6 | #============================================================================= 7 | my_chef_server_url = "https://chef-server.domain.com/organizations/oneview" 8 | 9 | node_name "CLIENT_NAME" 10 | client_key "#{current_dir}/CLIENT_NAME.pem" # Must have node & client creation privileges (ie admin group) 11 | 12 | validation_client_name "oneview-validator" 13 | validation_key "#{current_dir}/oneview-validator.pem" 14 | 15 | knife[:oneview_url] = 'https://my-oneview.my-domain.com' 16 | knife[:oneview_username] = 'Administrator' 17 | knife[:oneview_password] = 'password123' 18 | knife[:oneview_ignore_ssl] = true 19 | 20 | knife[:icsp_url] = 'https://my-icsp.my-domain.com' 21 | knife[:icsp_username] = 'Administrator' 22 | knife[:icsp_password] = 'password123' 23 | knife[:icsp_ignore_ssl] = true 24 | 25 | knife[:node_root_password] = 'password123' 26 | knife[:node_root_ssh_keys] = ['~/.ssh/id_rsa'] 27 | 28 | # For self-signed Chef server cert 29 | verify_api_cert false 30 | ssl_verify_mode :verify_none 31 | 32 | # If you're behind a proxy 33 | my_proxy = 'http://proxy.domain.com:8080' 34 | 35 | # Define your infrastructure here. This info gets populated into the recipe. Leave blank if you want to edit the recipe directly. 36 | # Recipe location: chef-provisioning-oneview/examples/cookbooks/provisioning_cookbook/recipes/default.rb 37 | knife[:example_recipe_options] = { 38 | 'action' => :converge, # :allocate, :ready, :stop, and :destroy are other options 39 | 'os_build' => 'CHEF-RHEL-6.5-x64', 40 | 'template' => 'Template - Web Server', 41 | 'gateway' => 'xx.xx.xx.xx', 42 | 'dns' => 'xx.xx.xx.xx', 43 | 'domain_name' => 'oneview-domain.com', 44 | 'mask' => '255.255.254.0', 45 | 'my_machines' => { 46 | 'chef-web01' => { 47 | 'ip4' => 'xxx.xx.xx.xx' 48 | }, 49 | 'chef-web02' => { 50 | 'dhcp' => true 51 | } 52 | } 53 | } 54 | #============================================================================= 55 | 56 | 57 | 58 | 59 | 60 | 61 | log_level :info 62 | log_location STDOUT 63 | cache_type 'BasicFile' 64 | cache_options( :path => "#{ENV['HOME']}/.chef/checksums" ) 65 | cookbook_path ["#{current_dir}/../cookbooks"] 66 | chef_server_url my_chef_server_url 67 | knife[:my_chef_server] = my_chef_server_url 68 | if my_proxy 69 | http_proxy my_proxy 70 | https_proxy my_proxy 71 | knife[:bootstrap_proxy] = my_proxy 72 | end 73 | -------------------------------------------------------------------------------- /spec/support/fake_icsp.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra/base' 2 | require 'json' 3 | 4 | class FakeIcsp < Sinatra::Base 5 | 6 | get '/rest/version' do 7 | json_response(200, 'version.json', '102') 8 | end 9 | 10 | get '/rest/index/resources' do 11 | version = env['HTTP_X_API_VERSION'] 12 | category = params['category'] 13 | return json_response(404, 'error_404.json', version) if category.nil? 14 | if category == 'osdserver' && params['query'].match(/osdServerSerialNumber:"VCGE9KB041"/) 15 | return json_response(200, 'server_by_sn_VCGE9KB041.json', version) 16 | elsif category == 'osdserver' && params['query'].match(/osdServerSerialNumber:"FAKESN"/) 17 | return json_response(200, 'server_by_sn_empty.json', version) 18 | else 19 | return json_response(404, 'error_404.json', version) 20 | end 21 | end 22 | 23 | get '/rest/os-deployment-servers' do 24 | version = env['HTTP_X_API_VERSION'] 25 | json_response(200, 'os-deployment-servers.json', version) 26 | end 27 | 28 | get '/rest/os-deployment-servers/:id' do 29 | version = env['HTTP_X_API_VERSION'] 30 | if params[:id] == '1670001' 31 | return json_response(200, 'os-deployment-servers_1670001.json', version) 32 | else 33 | return json_response(200, 'os-deployment-servers_fakesn.json', version) 34 | end 35 | end 36 | 37 | post '/rest/login-sessions' do 38 | version = env['HTTP_X_API_VERSION'] 39 | json_response(200, 'login.json', version) 40 | end 41 | 42 | get '/' do 43 | { message: 'Fake ICsp works!', method: env['REQUEST_METHOD'], content_type: env['CONTENT_TYPE'], query: env['QUERY_STRING'], 44 | api_version: env['HTTP_X_API_VERSION'], auth: env['HTTP_AUTH'], params: params }.to_json 45 | end 46 | 47 | post '/' do 48 | { message: 'Fake ICsp works!', method: env['REQUEST_METHOD'], content_type: env['CONTENT_TYPE'], query: env['QUERY_STRING'], 49 | api_version: env['HTTP_X_API_VERSION'], auth: env['HTTP_AUTH'], params: params }.to_json 50 | end 51 | 52 | put '/' do 53 | { message: 'Fake ICsp works!', method: env['REQUEST_METHOD'], content_type: env['CONTENT_TYPE'], query: env['QUERY_STRING'], 54 | api_version: env['HTTP_X_API_VERSION'], auth: env['HTTP_AUTH'], params: params }.to_json 55 | end 56 | 57 | delete '/' do 58 | { message: 'Fake ICsp works!', method: env['REQUEST_METHOD'], content_type: env['CONTENT_TYPE'], query: env['QUERY_STRING'], 59 | api_version: env['HTTP_X_API_VERSION'], auth: env['HTTP_AUTH'], params: params }.to_json 60 | end 61 | 62 | get '/*' do # All other paths should return a 404 error 63 | json_response(404, 'error_404.json', '102') 64 | end 65 | 66 | private 67 | 68 | def json_response(response_code, file_name, version = 102) 69 | content_type :json 70 | status response_code 71 | File.open(File.dirname(__FILE__) + "/fixtures/icsp/v#{version}/" + file_name, 'rb').read 72 | end 73 | end 74 | -------------------------------------------------------------------------------- /spec/unit/rest_api_spec.rb: -------------------------------------------------------------------------------- 1 | require_relative './../spec_helper' 2 | 3 | RSpec.describe Chef::Provisioning::OneViewDriver do 4 | include_context 'shared context' 5 | 6 | describe '#rest_api' do 7 | 8 | context 'fake_icsp' do 9 | it 'completes get request with correct parameters' do 10 | resp = @driver_200.instance_eval { rest_api(:icsp, :get, '/', {}) } 11 | expect(resp['method']).to eq('GET') 12 | expect(resp['message']).to eq('Fake ICsp works!') 13 | expect(resp['content_type']).to eq('application/json') 14 | expect(resp['api_version']).to eq(@driver_200.instance_variable_get('@icsp_api_version')) 15 | expect(resp['auth']).to eq(@icsp_key) 16 | end 17 | 18 | it 'completes post request with correct parameters' do 19 | resp = @driver_200.instance_eval { rest_api(:icsp, :post, '/', {}) } 20 | expect(resp['method']).to eq('POST') 21 | expect(resp['message']).to eq('Fake ICsp works!') 22 | expect(resp['content_type']).to eq('application/json') 23 | expect(resp['api_version']).to eq(@driver_200.instance_variable_get('@icsp_api_version')) 24 | expect(resp['auth']).to eq(@icsp_key) 25 | end 26 | 27 | it 'completes put request with correct parameters' do 28 | resp = @driver_200.instance_eval { rest_api(:icsp, :put, '/', {}) } 29 | expect(resp['method']).to eq('PUT') 30 | expect(resp['message']).to eq('Fake ICsp works!') 31 | expect(resp['content_type']).to eq('application/json') 32 | expect(resp['api_version']).to eq(nil) 33 | expect(resp['auth']).to eq(@icsp_key) 34 | end 35 | 36 | it 'completes delete request with correct parameters' do 37 | resp = @driver_200.instance_eval { rest_api(:icsp, :delete, '/', {}) } 38 | expect(resp['method']).to eq('DELETE') 39 | expect(resp['message']).to eq('Fake ICsp works!') 40 | expect(resp['content_type']).to eq('application/json') 41 | expect(resp['api_version']).to eq(@driver_200.instance_variable_get('@icsp_api_version')) 42 | expect(resp['auth']).to eq(@icsp_key) 43 | end 44 | 45 | it 'returns 404 error for invalid get request' do 46 | resp = @driver_200.instance_eval { rest_api(:icsp, :get, '/invalid_path', {}) } 47 | expect(resp['errorCode']).to eq('GENERIC_HTTP_404') 48 | end 49 | end 50 | 51 | it 'only accepts oneview or icsp hosts parameter' do 52 | expect { @driver_200.instance_eval { rest_api(:invalid, :get, '/', {}) } }.to raise_error(/Invalid rest host/) 53 | end 54 | 55 | it 'only accepts rest action parameters' do 56 | expect { @driver_200.instance_eval { rest_api(:icsp, :invalid, '/', {}) } }.to raise_error(/Invalid rest call/) 57 | end 58 | 59 | end 60 | 61 | describe 'get api versions' do 62 | 63 | it 'can parse the icsp api version' do 64 | expect(@driver_200.instance_eval { get_icsp_api_version }).to match(102) 65 | end 66 | end 67 | 68 | end 69 | -------------------------------------------------------------------------------- /examples/cookbooks/provisioning_cookbook/recipes/zero.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: provisioning_cookbook 3 | # Recipe:: default 4 | # 5 | # Copyright (C) Hewlett Packard Enterprise 6 | # 7 | # All rights reserved - Do Not Redistribute 8 | # 9 | 10 | knife_options = Chef::Config.knife[:example_recipe_options] || {} 11 | 12 | #==================================================== 13 | #================== Custom Options ================== 14 | #==================================================== 15 | #============ NOTE: Fill this section out =========== 16 | 17 | os_build = knife_options['os_build'] || 'CHEF-RHEL-6.5-x64' 18 | my_template = knife_options['template'] || 'Template - Web Server' 19 | gateway = knife_options['gateway'] || 'xx.xx.xx.xx' 20 | dns = knife_options['dns'] || 'xx.xx.xx.xx' 21 | domain_name = knife_options['domain_name'] || 'oneview-domain.com' 22 | mask = knife_options['mask'] || '255.255.254.0' 23 | 24 | # Hash that defines the machines to build. IP is the only attribute right now, but change as necessary. 25 | my_machines = knife_options['my_machines'] || { 26 | 'chef-web01' => { 27 | 'ip4' => 'xx.xx.xx.xx' 28 | }, 29 | 'chef-web02' => { 30 | 'ip4' => 'xx.xx.xx.xx' 31 | } 32 | } 33 | #==================================================== 34 | #================ End Custom Options ================ 35 | #==================================================== 36 | 37 | require 'chef/provisioning' 38 | 39 | with_driver 'oneview' 40 | 41 | action_verb = knife_options['action'] || :setup 42 | if [:converge, :converge_only].include?(action_verb) 43 | log "\n\nWARNING: Action '#{action_verb}' might not work properly with Chef Zero. You've been warned...\n\n" do 44 | level :warn 45 | end 46 | end 47 | 48 | machine_batch 'oneview-machine-batch' do 49 | # Note: Enclosing the machine resources in this machine_batch block allows them to provision in parallel. 50 | 51 | action action_verb 52 | 53 | my_machines.each do |m_name, options| 54 | 55 | machine m_name do 56 | 57 | machine_options :driver_options => { 58 | :server_template => my_template, 59 | :os_build => os_build, 60 | :host_name => m_name, 61 | :ip_address => options['ip4'], # For bootstrapping only. 62 | 63 | :domainType => 'workgroup', 64 | :domainName => domain_name, 65 | :gateway => gateway, 66 | :dns => dns, 67 | :connections => { 68 | #1 => { ... } (Reserved for PXE) 69 | 2 => { 70 | :ip4Address => options['ip4'], 71 | :mask => mask, 72 | :dhcp => false 73 | } 74 | } 75 | }, 76 | :custom_attributes => {}, 77 | :transport_options => { 78 | :ssh_options => { 79 | :password => Chef::Config.knife[:node_root_password] 80 | } 81 | }, 82 | :convergence_options => { 83 | :ssl_verify_mode => :verify_none, 84 | :bootstrap_proxy => Chef::Config.knife[:bootstrap_proxy] 85 | } 86 | 87 | chef_environment '_default' 88 | converge false 89 | end # End machine resource block 90 | 91 | end # End my_machines.each loop 92 | 93 | end # End machine_batch resource block 94 | -------------------------------------------------------------------------------- /spec/shared_context.rb: -------------------------------------------------------------------------------- 1 | RSpec.shared_context 'shared context', a: :b do 2 | 3 | domain = 'my-domain.com' 4 | chef_server = "https://my-chef-server.#{domain}/organizations/oneview" 5 | oneview = "https://my-oneview.#{domain}" 6 | icsp = "https://my-icsp.#{domain}" 7 | 8 | let(:oneview_url) do 9 | 'https://oneview.example.com' 10 | end 11 | 12 | let(:knife_config) do 13 | { knife: { 14 | oneview_url: oneview, 15 | oneview_username: 'Administrator', 16 | oneview_password: 'password12', 17 | oneview_ignore_ssl: true, 18 | oneview_timeout: 15, 19 | 20 | icsp_url: icsp, 21 | icsp_username: 'administrator', 22 | icsp_password: 'password123' 23 | } } 24 | end 25 | 26 | let(:driver_config) do 27 | { 28 | driver_options: { 29 | oneview: { token: @oneview_token }, 30 | icsp: { url: @icsp_url, user: @icsp_user, password: @icsp_password } 31 | }, 32 | knife: {} 33 | } 34 | end 35 | 36 | let(:valid_machine_options) do 37 | { 38 | convergence_options: { 39 | ssl_verify_mode: :verify_none, 40 | bootstrap_proxy: "http://proxy.#{domain}:8080", 41 | chef_server: { 42 | chef_server_url: chef_server, 43 | options: { 44 | client_name: 'user', 45 | signing_key_filename: 'spec/fixtures/.chef/user.pem' 46 | } 47 | } 48 | }, 49 | driver_options: { 50 | server_template: 'Template - Web Server', 51 | os_build: 'CHEF-RHEL-6.5-x64', 52 | host_name: 'chef-web01', 53 | profile_name: 'chef-web01', 54 | ip_address: '192.168.1.2', 55 | domainType: 'workgroup', 56 | domainName: domain, 57 | gateway: '192.168.1.1', 58 | dns: '192.168.1.1,10.1.1.1', 59 | connections: { 60 | 1 => { dhcp: true, team: 'team1' }, 61 | 2 => { ip4Address: '192.168.1.2', mask: '255.255.254.0', dhcp: false, team: 'team1' } 62 | } 63 | }, 64 | custom_attributes: { 65 | }, 66 | transport_options: { 67 | ssh_options: { password: 'password1234' } 68 | } 69 | } 70 | end 71 | 72 | let(:action_handler) do 73 | ChefProvisioningOneviewHelpers::FakeActionHandler.new 74 | end 75 | 76 | let(:machine_spec) do 77 | ChefProvisioningOneviewHelpers::FakeMachineSpec.new('server-1', 'VCGE9KB041') 78 | end 79 | 80 | let(:machine_spec2) do 81 | ChefProvisioningOneviewHelpers::FakeMachineSpec.new('server-2', '789123') 82 | end 83 | 84 | before :each do 85 | # @oneview_key = 'A954A2A6Psy7Alg3HApAcEbAcAwa-ftA' 86 | # @icsp_key = 'AA_aaAaa3AA3Aa0_aAaAA4AAAA3AAAAA' 87 | # @url = oneview 88 | # @canonical_url = "oneview:#{@url}" 89 | # @instance = Chef::Provisioning::OneViewDriver.new(@canonical_url, knife_config) 90 | 91 | @driver_200 = Chef::Provisioning::OneViewDriver.new(@canonical_url, driver_config) 92 | @ov_200 = @driver_200.instance_variable_get(:@ov) 93 | driver_config[:driver_options][:oneview][:api_version] = 120 94 | @driver_120 = Chef::Provisioning::OneViewDriver.new(@canonical_url, driver_config) 95 | @ov_120 = @driver_120.instance_variable_get(:@ov) 96 | end 97 | 98 | end 99 | -------------------------------------------------------------------------------- /spec/unit/create_machine_spec.rb: -------------------------------------------------------------------------------- 1 | require_relative './../spec_helper' 2 | 3 | RSpec.describe Chef::Provisioning::OneViewDriver do 4 | describe '#create_machine' do 5 | include_context 'shared context' 6 | 7 | let(:machine_name) do 8 | 'chef-web01' 9 | end 10 | 11 | before :each do 12 | options = { name: 'chef-web01', uri: '/rest/fake', serverHardwareTypeUri: '/rest/fake2', enclosureGroupUri: '/rest/fake3' } 13 | @profile = OneviewSDK::ServerProfile.new(@ov_200, options) 14 | @hw = OneviewSDK::ServerHardware.new(@ov_200, name: 'Enclosure-1, bay 1', uri: '/rest/fake4') 15 | end 16 | 17 | context 'when the profile already exists' do 18 | it 'skips creating the profile' do 19 | expect(OneviewSDK::ServerProfile).to receive(:find_by).and_return([@profile]) 20 | expect(@driver_200).to_not receive(:get_oneview_template) 21 | a = action_handler 22 | m = machine_name 23 | o = valid_machine_options 24 | p = @driver_200.instance_eval { create_machine(a, m, o) } 25 | expect(p).to eq(@profile) 26 | end 27 | end 28 | 29 | context 'when the profile does not exist' do 30 | it 'creates a new profile' do 31 | expect(OneviewSDK::ServerProfile).to receive(:find_by).and_return([]) 32 | a = action_handler 33 | m = machine_name 34 | o = valid_machine_options 35 | expect(@driver_200).to receive(:profile_from_template) 36 | .with(o[:driver_options][:server_template], o[:driver_options][:profile_name]).and_return(@profile) 37 | expect(@driver_200).to receive(:available_hardware_for_profile) 38 | .with(@profile, o[:driver_options][:server_location]).and_return(@hw) 39 | expect(@hw).to receive(:power_off).and_return(true) 40 | expect(@profile).to receive(:set_server_hardware).with(@hw).and_call_original 41 | expect(@driver_200).to receive(:update_san_info).and_return(true) 42 | expect(@ov_200).to receive(:rest_post).and_return(FakeResponse.new({}, 202)) 43 | expect(@profile).to receive(:retrieve!).and_return(true) 44 | p = @driver_200.instance_eval { create_machine(a, m, o) } 45 | expect(p[:name]).to eq(o[:driver_options][:profile_name]) 46 | expect(p[:serverHardwareTypeUri]).to eq('/rest/fake2') 47 | expect(p[:enclosureGroupUri]).to eq('/rest/fake3') 48 | expect(p[:serverHardwareUri]).to eq('/rest/fake4') 49 | end 50 | 51 | it 'prints an error message if the creation failed' do 52 | expect(OneviewSDK::ServerProfile).to receive(:find_by).and_return([]) 53 | a = action_handler 54 | m = machine_name 55 | o = valid_machine_options 56 | expect(@driver_200).to receive(:profile_from_template) 57 | .with(o[:driver_options][:server_template], o[:driver_options][:profile_name]).and_return(@profile) 58 | expect(@driver_200).to receive(:available_hardware_for_profile) 59 | .with(@profile, o[:driver_options][:server_location]).and_return(@hw) 60 | expect(@hw).to receive(:power_off).and_return(true) 61 | expect(@profile).to receive(:set_server_hardware).with(@hw).and_call_original 62 | expect(@driver_200).to receive(:update_san_info).and_return(true) 63 | expect(@ov_200).to receive(:rest_post).and_return(FakeResponse.new({}, 500)) 64 | expect { @driver_200.instance_eval { create_machine(a, m, o) } }.to raise_error(/Server profile couldn't be created/) 65 | end 66 | end 67 | 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /lib/chef/provisioning/customize_machine.rb: -------------------------------------------------------------------------------- 1 | module OneviewChefProvisioningDriver 2 | # Handles OS install and network configuration 3 | module CustomizeMachine 4 | # Use ICSP to install OS 5 | def customize_machine(action_handler, machine_spec, machine_options, profile) 6 | machine_name = machine_spec.name 7 | # Wait for server profile to finish building 8 | wait_for_profile(action_handler, machine_name, profile) 9 | profile.refresh 10 | 11 | # Configure SAN storage (if applicable) 12 | enable_boot_from_san(action_handler, machine_name, profile) unless machine_spec.reference['network_personalitation_finished'] 13 | 14 | # Make sure server is started 15 | profile.get_server_hardware.power_on 16 | 17 | return if @icsp_ignore == true 18 | 19 | # Get ICSP servers to poll and wait until server PXE complete (to make sure ICSP is available). 20 | my_server = nil 21 | action_handler.perform_action "Wait for #{machine_name} to boot into HP Intelligent Provisioning" do 22 | action_handler.report_progress "INFO: Waiting for #{machine_name} to PXE boot into HP Intelligent Provisioning" 23 | 360.times do # Wait for up to 1 hr 24 | my_server = get_icsp_server_by_sn(profile['serialNumber']) 25 | break unless my_server.nil? 26 | print '.' 27 | sleep 10 28 | end 29 | raise "Timeout waiting for server #{machine_name} to register with ICSP" if my_server.nil? 30 | end 31 | 32 | icsp_configure_nic_teams(machine_options, profile) 33 | 34 | icsp_set_custom_attributes(machine_options, my_server) 35 | 36 | icsp_run_os_install(action_handler, machine_spec, machine_options, my_server, profile) 37 | 38 | # Customize networking 39 | if !machine_spec.reference['network_personalitation_finished'] || machine_options[:driver_options][:force_network_update] 40 | 41 | icsp_configure_networking(action_handler, machine_spec, machine_options, my_server, profile) 42 | 43 | # Switch deploy networks to post-deploy networks if specified 44 | if machine_options[:driver_options][:connections] 45 | available_networks = profile.available_networks 46 | machine_options[:driver_options][:connections].each do |id, data| 47 | next unless data && data[:net] && data[:deployNet] 48 | action_handler.perform_action "Perform network flipping on #{machine_name}, connection #{id}" do 49 | action_handler.report_progress "INFO: Performing network flipping on #{machine_name}, connection #{id}" 50 | deploy_network = available_networks['ethernetNetworks'].find { |n| n['name'] == data[:deployNet] } 51 | new_network = available_networks['ethernetNetworks'].find { |n| n['name'] == data[:net] } 52 | raise "Failed to perform network flipping on #{machine_name}, connection #{id}. '#{data[:net]}' network not found" if new_network.nil? 53 | raise "Failed to perform network flipping on #{machine_name}, connection #{id}. '#{data[:deployNet]}' network not found" if deploy_network.nil? 54 | profile.refresh 55 | profile['connections'].find { |c| c['networkUri'] == deploy_network['uri'] }['networkUri'] = new_network['uri'] 56 | profile.update 57 | end 58 | end 59 | end 60 | machine_spec.reference['network_personalitation_finished'] = true 61 | end 62 | 63 | my_server = rest_api(:icsp, :get, my_server['uri']) 64 | end 65 | end 66 | end 67 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | This directory contains everything you need to start provisioning with OneView and Chef. 2 | 3 | ## Usage with a Chef Server 4 | **Requirements:** ChefDK installed on your workstation. 5 | 6 | 1. Create `.chef/.pem` and `.chef/oneview-validator.pem` files, and populate them with your client and validator keys for your Chef server org. 7 | 2. Create `.chef/knife.rb` using the `.chef/knife.rb.example` file as a template. Fill it with the correct info for your Chef server. It also contains a data hash for provisioning the oneview machines. You can either fill the data out here, or advanced users may edit the recipe at `cookbooks/provisioning_cookbook/recipes/default.rb` directly. 8 | 3. Then from this (examples) directory, run: 9 | 10 | ```bash 11 | # Upload the cookbooks to your Chef server using berkshelf: 12 | $ berks install 13 | $ berks upload 14 | 15 | # Install chef-provisioning-oneview as a Chef gem: 16 | $ chef-client -z -o provisioning_cookbook::install_gems 17 | 18 | # Run the provisioning cookbook: 19 | $ chef-client -z -o provisioning_cookbook 20 | ``` 21 | 22 | ## Usage with Chef Zero 23 | **Requirements:** chef-client or ChefDK installed on your workstation. 24 | 25 | **NOTE:** This provisioner will provision the node, install the OS, and configure networking, but it **won't** be able to bootstrap the node and apply a runlist. You'll have to bootstrap it as a seperate step. This is because zero will pass a chef_server_url parameter of "chefzero://localhost:8889" to the node at bootstrap time, which the node won't be able to resolve to your machine. 26 | 1. Create `.chef/knife.rb` using the `.chef/knife.rb.example` file as a template. Fill it with the correct info for your OneView and ICSP instances. You don't have to worry about the Chef Server info or the client or validator keys. This file also contains a data hash for provisioning the oneview machines. You can either fill the data out here, or advanced users may edit the recipe at `cookbooks/provisioning_cookbook/recipes/zero.rb` directly. 27 | 2. Then from this (examples) directory, run: 28 | 29 | ```bash 30 | # Install chef-provisioning-oneview as a Chef gem: 31 | $ chef-client -z -o provisioning_cookbook::install_gems 32 | 33 | # Run the provisioning cookbook: 34 | $ chef-client -z -o provisioning_cookbook::zero 35 | ``` 36 | 37 | 4. If you want to continue and bootstrap the machine, you'll have two options: (1) set up a Chef Server and bootstrap it like normal or (2) copy the cookbooks onto the node and run chef-client in local (zero) mode from there. 38 | 39 | ## Building a Docker container with OneView provisioning and ChefDK 40 | The `examples\Docker\` contains a `Dockerfile` that can be used to build a container with the latest components that can be used to automate HPE OneView with Chef. To build the container the Dockerfile will need copying to a docker host then the `$ docker build` command can be used to pull all the requirements and build the container. 41 | 42 | Build Example: 43 | 44 | `$ docker build -t OneView-Chef -f ` 45 | 46 | This container can then be run using the `$ docker run OneView-Chef` command. Further documentation can be found at https://hub.docker.com/r/thebsdbox/oneview-chef/ for passing recipes and configuration into the docker container. 47 | 48 | ## Troubleshooting 49 | 50 | - One of the most common problems people run into is ssl certificate verification issues with private Chef servers. See [ssl_issues.md](ssl_issues.md) to fix these errors. 51 | 52 | - Also see the [Trouleshooting wiki page](https://github.com/HewlettPackard/chef-provisioning-oneview/wiki/Troubleshooting) 53 | -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v200/server-profile-templates_WebServerTemplate.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "ServerProfileTemplateListV1", 3 | "members": [ 4 | { 5 | "type": "ServerProfileTemplateV1", 6 | "uri": "/rest/server-profile-templates/d64da635-f08a-41d4-b6eb-6517206a8bae", 7 | "name": "Web Server Template", 8 | "description": "", 9 | "serverProfileDescription": "web server template", 10 | "serverHardwareTypeUri": "/rest/server-hardware-types/5B42EABE-5140-4E38-91F0-68367B529DE9", 11 | "enclosureGroupUri": "/rest/enclosure-groups/c0f86584-5a82-4480-ad13-8ed6544d6c98", 12 | "affinity": "Bay", 13 | "hideUnusedFlexNics": true, 14 | "macType": "Virtual", 15 | "wwnType": "Virtual", 16 | "serialNumberType": "Virtual", 17 | "firmware": { 18 | "manageFirmware": false, 19 | "firmwareInstallType": null, 20 | "forceInstallFirmware": false, 21 | "firmwareBaselineUri": null 22 | }, 23 | "connections": [ 24 | { 25 | "id": 7, 26 | "name": "Altair PXE", 27 | "functionType": "Ethernet", 28 | "networkUri": "/rest/ethernet-networks/7984a764-69ae-48c0-aec2-780d4f0366f8", 29 | "portId": "Flb 1:1-a", 30 | "requestedVFs": "Auto", 31 | "requestedMbps": "1000", 32 | "boot": { 33 | "priority": "Primary" 34 | } 35 | }, 36 | { 37 | "id": 8, 38 | "name": "Corpnet", 39 | "functionType": "Ethernet", 40 | "networkUri": "/rest/ethernet-networks/52b6f044-f51b-4d4c-8d59-497c14c4681c", 41 | "portId": "Flb 1:1-c", 42 | "requestedVFs": "Auto", 43 | "requestedMbps": "2500", 44 | "boot": { 45 | "priority": "NotBootable" 46 | } 47 | } 48 | ], 49 | "bootMode": null, 50 | "boot": { 51 | "manageBoot": true, 52 | "order": [ 53 | "HardDisk", 54 | "PXE", 55 | "CD", 56 | "Floppy", 57 | "USB" 58 | ] 59 | }, 60 | "bios": { 61 | "manageBios": false, 62 | "overriddenSettings": [ 63 | 64 | ] 65 | }, 66 | "localStorage": { 67 | "controllers": [ 68 | { 69 | "slotNumber": "0", 70 | "managed": true, 71 | "mode": "RAID", 72 | "initialize": true, 73 | "logicalDrives": [ 74 | { 75 | "raidLevel": "RAID1", 76 | "bootable": true, 77 | "driveName": "boot", 78 | "numPhysicalDrives": 2, 79 | "driveTechnology": null 80 | } 81 | ] 82 | } 83 | ] 84 | }, 85 | "sanStorage": { 86 | "manageSanStorage": false, 87 | "volumeAttachments": [ 88 | 89 | ] 90 | }, 91 | "category": "server-profile-templates", 92 | "created": "2015-09-04T17:15:39.249Z", 93 | "modified": "2015-09-04T17:41:44.999Z", 94 | "status": "OK", 95 | "state": null, 96 | "eTag": "1441388504999/3" 97 | } 98 | ], 99 | "nextPageUri": null, 100 | "start": 0, 101 | "prevPageUri": null, 102 | "total": 1, 103 | "count": 1, 104 | "modified": "2015-09-15T23:18:39.561Z", 105 | "eTag": "2015-09-15T23:18:39.561Z", 106 | "created": "2015-09-15T23:18:39.561Z", 107 | "category": "server-profile-templates", 108 | "uri": "/rest/server-profile-templates?filter=%22name%20matches%20'Web%20Server%20Template'%22&sort=name:asc&start=0&count=64" 109 | } 110 | -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v200/server-profile-templates_new-profile_WebServerTemplate.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "ServerProfileV5", 3 | "uri": null, 4 | "name": null, 5 | "description": "web server template", 6 | "serialNumber": null, 7 | "uuid": null, 8 | "serverProfileTemplateUri": "/rest/server-profile-templates/d64da635-f08a-41d4-b6eb-6517206a8bae", 9 | "templateCompliance": "Unknown", 10 | "serverHardwareUri": null, 11 | "serverHardwareTypeUri": "/rest/server-hardware-types/5B42EABE-5140-4E38-91F0-68367B529DE9", 12 | "enclosureGroupUri": "/rest/enclosure-groups/c0f86584-5a82-4480-ad13-8ed6544d6c98", 13 | "enclosureUri": null, 14 | "enclosureBay": null, 15 | "affinity": "Bay", 16 | "associatedServer": null, 17 | "hideUnusedFlexNics": true, 18 | "firmware": { 19 | "firmwareInstallType": null, 20 | "forceInstallFirmware": false, 21 | "manageFirmware": false, 22 | "firmwareBaselineUri": null 23 | }, 24 | "macType": "Virtual", 25 | "wwnType": "Virtual", 26 | "serialNumberType": "Virtual", 27 | "category": "server-profiles", 28 | "created": null, 29 | "modified": null, 30 | "status": "OK", 31 | "state": "Creating", 32 | "inProgress": false, 33 | "taskUri": null, 34 | "connections": [ 35 | { 36 | "id": 7, 37 | "name": "Altair PXE", 38 | "functionType": "Ethernet", 39 | "deploymentStatus": null, 40 | "networkUri": "/rest/ethernet-networks/7984a764-69ae-48c0-aec2-780d4f0366f8", 41 | "portId": "Flb 1:1-a", 42 | "requestedVFs": "Auto", 43 | "allocatedVFs": null, 44 | "interconnectUri": null, 45 | "macType": null, 46 | "wwpnType": null, 47 | "mac": null, 48 | "wwnn": null, 49 | "wwpn": null, 50 | "requestedMbps": "1000", 51 | "allocatedMbps": 0, 52 | "maximumMbps": 0, 53 | "boot": { 54 | "priority": "Primary" 55 | } 56 | }, 57 | { 58 | "id": 8, 59 | "name": "Corpnet", 60 | "functionType": "Ethernet", 61 | "deploymentStatus": null, 62 | "networkUri": "/rest/ethernet-networks/52b6f044-f51b-4d4c-8d59-497c14c4681c", 63 | "portId": "Flb 1:1-c", 64 | "requestedVFs": "Auto", 65 | "allocatedVFs": null, 66 | "interconnectUri": null, 67 | "macType": null, 68 | "wwpnType": null, 69 | "mac": null, 70 | "wwnn": null, 71 | "wwpn": null, 72 | "requestedMbps": "2500", 73 | "allocatedMbps": 0, 74 | "maximumMbps": 0, 75 | "boot": { 76 | "priority": "NotBootable" 77 | } 78 | } 79 | ], 80 | "bootMode": null, 81 | "boot": { 82 | "order": [ 83 | "HardDisk", 84 | "PXE", 85 | "CD", 86 | "Floppy", 87 | "USB" 88 | ], 89 | "manageBoot": true 90 | }, 91 | "bios": { 92 | "overriddenSettings": [ 93 | 94 | ], 95 | "manageBios": false 96 | }, 97 | "localStorage": { 98 | "controllers": [ 99 | { 100 | "slotNumber": "0", 101 | "managed": true, 102 | "mode": "RAID", 103 | "initialize": true, 104 | "importConfiguration": false, 105 | "logicalDrives": [ 106 | { 107 | "driveNumber": null, 108 | "raidLevel": "RAID1", 109 | "numPhysicalDrives": 2, 110 | "driveTechnology": null, 111 | "bootable": true, 112 | "driveName": "boot" 113 | } 114 | ] 115 | } 116 | ] 117 | }, 118 | "sanStorage": { 119 | "volumeAttachments": [ 120 | 121 | ], 122 | "manageSanStorage": false 123 | }, 124 | "eTag": null 125 | } 126 | -------------------------------------------------------------------------------- /examples/cookbooks/my_apache_server/files/default/oneview/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | HPE OneView and Chef 5 | 6 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 |
28 |
29 | 30 | 31 |
32 |
33 |
34 |
35 |

HPE OneView and Chef

36 |

End-to-end infrastructure to application automation

37 |
38 |
39 |
40 | 41 | 42 |
43 |
44 |
45 |

Eliminate infrastructure complexity with automation simplicity

46 |

HPE OneView delivers simplified and consistent infrastructure management, unifying processes, user interface, and application programming interfaces (APIs) across multiple generations of HPE compute, storage, and networking. HPE OneView takes simplicity to the next level, by serving as an automation hub that allows other management tools—like Chef—to consume HPE bare-metal infrastructure as code, and incorporate HPE OneView templates and profiles into Chef recipes.

47 |

With Chef, you can automate how you build, deploy, and manage your infrastructure. Your infrastructure becomes as versionable, testable, and repeatable as application code.

48 |
49 |
50 |

Learn more

51 |

52 | hpe.com/info/oneview 53 |

54 |

55 | chef.io 56 |

57 | 58 |

Chef logo

59 |
60 |
61 |
62 |
63 | 64 | 65 |
66 |
67 | 68 | 69 | -------------------------------------------------------------------------------- /examples/cookbooks/provisioning_cookbook/recipes/default.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: provisioning_cookbook 3 | # Recipe:: default 4 | # 5 | # Copyright (C) Hewlett Packard Enterprise 6 | # 7 | # All rights reserved - Do Not Redistribute 8 | # 9 | 10 | knife_options = Chef::Config.knife[:example_recipe_options] || {} 11 | 12 | #==================================================== 13 | #================== Custom Options ================== 14 | #==================================================== 15 | #============ NOTE: Fill this section out =========== 16 | 17 | os_build = knife_options['os_build'] || 'CHEF-RHEL-6.5-x64' 18 | my_template = knife_options['template'] || 'Template - Web Server' 19 | gateway = knife_options['gateway'] || 'xx.xx.xx.xx' 20 | dns = knife_options['dns'] || 'xx.xx.xx.xx' 21 | domain_name = knife_options['domain_name'] || 'oneview-domain.com' 22 | mask = knife_options['mask'] || '255.255.254.0' 23 | action_verb = knife_options['action'] || :converge # :stop and :destroy are other options 24 | 25 | # Hash that defines the machines to build. IP is the only attribute right now, but change as necessary. 26 | my_machines = knife_options['my_machines'] || { 27 | 'chef-web01' => { 28 | 'ip4' => 'xx.xx.xx.xx' 29 | }, 30 | 'chef-web02' => { 31 | 'ip4' => 'xx.xx.xx.xx' 32 | } 33 | } 34 | #==================================================== 35 | #================ End Custom Options ================ 36 | #==================================================== 37 | 38 | require 'chef/provisioning' 39 | 40 | with_driver 'oneview' 41 | 42 | with_chef_server Chef::Config.knife[:my_chef_server], 43 | :client_name => Chef::Config[:node_name], 44 | :signing_key_filename => Chef::Config[:client_key] 45 | # Note: The keys specified above must have node & client creation privileges (ie admin group members). 46 | # You can also use the validator client, by switching the above options to: 47 | # Chef::Config[:validation_client_name] and Chef::Config[:validation_key] 48 | 49 | log "Using '#{Chef::Config[:node_name]}' for knife client name" 50 | log "Using '#{Chef::Config[:client_key]}' for knife client key" 51 | 52 | 53 | machine_batch 'oneview-machine-batch' do 54 | # Note: Enclosing the machine resources in this machine_batch block allows them to provision in parallel. 55 | 56 | action action_verb 57 | 58 | my_machines.each do |m_name, options| 59 | 60 | machine m_name do 61 | recipe 'my_apache_server' 62 | 63 | machine_options :driver_options => { 64 | :server_template => my_template, 65 | :os_build => os_build, 66 | :host_name => m_name, 67 | # :ip_address => options['ip4'], # For bootstrapping. Deprecated in favor of { bootstrap: true } in connection 68 | 69 | :domainType => 'workgroup', 70 | :domainName => domain_name, 71 | :gateway => gateway, 72 | :mask => mask, 73 | :dns => dns, 74 | :connections => { 75 | # 1 => { dhcp: true }, # (Reserved for PXE) 76 | 2 => { 77 | :ip4Address => options['ip4'], 78 | :dhcp => options['dhcp'] || false, 79 | :bootstrap => true 80 | } 81 | } 82 | }, 83 | :custom_attributes => {}, 84 | :transport_options => { 85 | :ssh_options => { 86 | :password => Chef::Config.knife[:node_root_password], 87 | :auth_methods => ['password', 'publickey'], 88 | :keys => Chef::Config.knife[:node_root_ssh_keys] || [] 89 | } 90 | }, 91 | :convergence_options => { 92 | :ssl_verify_mode => :verify_none, 93 | :bootstrap_proxy => Chef::Config.knife[:bootstrap_proxy] 94 | } 95 | 96 | chef_environment '_default' 97 | converge true 98 | end # End machine resource block 99 | 100 | end # End my_machines.each loop 101 | 102 | end # End machine_batch resource block 103 | -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v120/server-profiles_name_Template-WebServer.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "ServerProfileListV4", 3 | "members": [ 4 | { 5 | "type": "ServerProfileV4", 6 | "uri": "/rest/server-profiles/a16654c6-d12d-4e42-aa04-8868cf3dc31a", 7 | "name": "Template - Web Server", 8 | "description": "Web server machine template", 9 | "serialNumber": "VCGE9KB035", 10 | "uuid": "a16654c6-d12d-4e42-aa04-8868cf3dc31a", 11 | "serverHardwareUri": null, 12 | "serverHardwareTypeUri": "/rest/server-hardware-types/2947DC35-BE48-4075-A3FD-254A9B42F5BD", 13 | "enclosureGroupUri": "/rest/enclosure-groups/3a11ccdd-b352-4046-a568-a8b0faa6cc39", 14 | "enclosureUri": null, 15 | "enclosureBay": null, 16 | "affinity": "Bay", 17 | "associatedServer": null, 18 | "hideUnusedFlexNics": true, 19 | "firmware": { 20 | "forceInstallFirmware": false, 21 | "manageFirmware": true, 22 | "firmwareBaselineUri": "/rest/firmware-drivers/bp-hp-service-pack-for-proliant-oneview-2014-11-30-05" 23 | }, 24 | "macType": "Virtual", 25 | "wwnType": "Virtual", 26 | "serialNumberType": "Virtual", 27 | "category": "server-profiles", 28 | "created": "20150730T115836.727Z", 29 | "modified": "20150807T051446.275Z", 30 | "status": "OK", 31 | "state": "Normal", 32 | "inProgress": false, 33 | "taskUri": "/rest/tasks/26235118-827A-445D-9E5D-F2BBCAC8E9E8", 34 | "connections": [ 35 | { 36 | "id": 1, 37 | "name": "Altair PXE 1133", 38 | "functionType": "Ethernet", 39 | "deploymentStatus": "Reserved", 40 | "networkUri": "/rest/ethernet-networks/02b0b5c3-1a0a-4d5f-b5c9-0c7532cb1e5e", 41 | "portId": "Flb 1:1-a", 42 | "interconnectUri": null, 43 | "macType": "Virtual", 44 | "wwpnType": "Virtual", 45 | "mac": "11:11:11:11:00:D8", 46 | "wwnn": null, 47 | "wwpn": null, 48 | "requestedMbps": "2500", 49 | "allocatedMbps": 2500, 50 | "maximumMbps": 10000, 51 | "boot": { 52 | "priority": "Primary" 53 | } 54 | }, 55 | { 56 | "id": 2, 57 | "name": "corpnet 10", 58 | "functionType": "Ethernet", 59 | "deploymentStatus": "Reserved", 60 | "networkUri": "/rest/ethernet-networks/7a4698ae-5933-4e2e-8af3-57893c23a2d2", 61 | "portId": "Flb 1:2-a", 62 | "interconnectUri": null, 63 | "macType": "Virtual", 64 | "wwpnType": "Virtual", 65 | "mac": "11:11:11:11:00:D9", 66 | "wwnn": null, 67 | "wwpn": null, 68 | "requestedMbps": "2500", 69 | "allocatedMbps": 2500, 70 | "maximumMbps": 10000, 71 | "boot": { 72 | "priority": "NotBootable" 73 | } 74 | } 75 | ], 76 | "bootMode": null, 77 | "boot": { 78 | "manageBoot": true, 79 | "order": [ 80 | "HardDisk", 81 | "PXE", 82 | "CD", 83 | "Floppy", 84 | "USB" 85 | ] 86 | }, 87 | "bios": { 88 | "manageBios": true, 89 | "overriddenSettings": [ 90 | { 91 | "id": "176", 92 | "value": "1" 93 | }, 94 | { 95 | "id": "181", 96 | "value": "1" 97 | }, 98 | { 99 | "id": "158", 100 | "value": "2" 101 | } 102 | ] 103 | }, 104 | "localStorage": { 105 | "logicalDrives": [ 106 | { 107 | "raidLevel": "RAID0", 108 | "bootable": true 109 | } 110 | ], 111 | "manageLocalStorage": true, 112 | "initialize": true 113 | }, 114 | "sanStorage": { 115 | "volumeAttachments": [ 116 | 117 | ], 118 | "manageSanStorage": false 119 | }, 120 | "eTag": "1438924486161/12" 121 | } 122 | ], 123 | "total": 1, 124 | "start": 0, 125 | "prevPageUri": null, 126 | "nextPageUri": null, 127 | "count": 1, 128 | "category": "server-profiles", 129 | "created": "20150810T223058.112Z", 130 | "eTag": "20150810T223058.112Z", 131 | "modified": "20150810T223058.112Z", 132 | "uri": "/rest/server-profiles?filter=name%20matches%20'Template%20-%20Web%20Server'&sort=name:asc" 133 | } -------------------------------------------------------------------------------- /lib/chef/provisioning/oneview/san_storage.rb: -------------------------------------------------------------------------------- 1 | module OneviewChefProvisioningDriver 2 | # Methods for configuring SAN storage on OneView 3 | module OneViewSanStorage 4 | def fill_volume_details(v) 5 | response = @ov.rest_get(v['volumeUri']) 6 | details = @ov.response_handler(response) 7 | v['volumeName'] = details['name'] 8 | v['permanent'] = details['isPermanent'] 9 | v['volumeShareable'] = details['shareable'] 10 | v['volumeProvisionType'] = details['provisionType'] 11 | v['volumeProvisionedCapacityBytes'] = details['provisionedCapacity'] 12 | v['volumeDescription'] = details['description'] 13 | v 14 | end 15 | 16 | # Prepare profile for SAN storage 17 | def update_san_info(machine_name, profile) 18 | san_storage = profile['sanStorage'] 19 | return profile unless san_storage && !san_storage['volumeAttachments'].empty? 20 | 21 | # Sanitize old SAN entries and fill in details 22 | boot_vols = [] 23 | san_storage['volumeAttachments'].each do |v| 24 | fill_volume_details(v) unless profile['serverProfileTemplateUri'] 25 | raise "#{machine_name}: Should know if volume is sharable:\n#{v}" unless v.key?('volumeShareable') 26 | 27 | # Match boot disks by name 28 | boot_vols.push(v['volumeName']) if v['volumeName'] =~ /^boot/i 29 | v['volumeName'] += " #{profile['name']}" unless v['volumeShareable'] # Append profile name to volume name 30 | 31 | next if profile['serverProfileTemplateUri'] # Only needed when coppied from profile 32 | v['state'] = nil 33 | v['status'] = nil 34 | v['storagePaths'].each { |s| s['status'] = nil } 35 | 36 | next if v['volumeShareable'] 37 | # It is private in the profile, so we will clone it 38 | v['volumeUri'] = nil 39 | 40 | # Assumes all cloned volumes are non-permanet. Might want some global config to control this 41 | v['permanent'] = false 42 | v['lun'] = nil if v['lunType'].casecmp('auto') == 0 43 | end 44 | raise "#{machine_name}: There should only be 1 SAN boot volume. Boot volumes: #{boot_vols}" if boot_vols.size > 1 45 | profile 46 | end 47 | 48 | # Make sure connections for SAN boot volumes are configured to boot from the correct SAN volume 49 | # @return false if no connections are available to configure 50 | def enable_boot_from_san(action_handler, machine_name, profile) 51 | return false if profile['connections'].nil? || profile['connections'].empty? 52 | 53 | # If there is a san volume we might need to update boot connections 54 | update_needed = false 55 | profile['sanStorage']['volumeAttachments'].each do |v| 56 | response = @ov.rest_get(v['volumeUri']) 57 | vol_details = @ov.response_handler(response) 58 | next unless vol_details['name'] =~ /^boot/i 59 | # Find the enabled path(s), get target wwpn, and then update connection, setting boot targets 60 | v['storagePaths'].each do |s| 61 | next if !s['isEnabled'] || s['storageTargets'].nil? || s['storageTargets'].empty? 62 | connection = profile['connections'].find { |c| c['id'] == s['connectionId'] } 63 | raise "#{machine_name}: Connection #{s['connectionId']} not found! Check SAN settings" unless connection 64 | if connection['boot'].nil? || connection['boot']['priority'] == 'NotBootable' 65 | msg = "#{machine_name}: Connection #{s['connectionId']} is labeled for boot, but the connection is not marked as bootable." 66 | raise "#{msg} Set the connection boot target to Primary or Secondary" 67 | end 68 | target = {} 69 | target['arrayWwpn'] = s['storageTargets'].first.delete(':') 70 | target['lun'] = v['lun'] 71 | unchanged = connection['boot']['targets'] && connection['boot']['targets'].first && 72 | connection['boot']['targets'].first['arrayWwpn'] == target['arrayWwpn'] && 73 | connection['boot']['targets'].first['lun'] == target['lun'] 74 | next if unchanged 75 | connection['boot']['targets'] = [target] 76 | update_needed = true 77 | end 78 | end 79 | 80 | if update_needed 81 | action_handler.perform_action "Enable SAN-bootable connections for #{machine_name}" do 82 | action_handler.report_progress "INFO: Enabling SAN-bootable connections for #{machine_name}" 83 | profile.get_server_hardware.power_off 84 | profile.update 85 | end 86 | profile.refresh 87 | end 88 | profile # Return profile 89 | end 90 | end 91 | end 92 | -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v120/server-profiles_name_chef-web01.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "ServerProfileListV4", 3 | "members": [ 4 | { 5 | "type": "ServerProfileV4", 6 | "uri": "/rest/server-profiles/1c5e807d-acbe-4ee8-868b-2fb0b6504474", 7 | "name": "chef-web01", 8 | "description": "Web server machine template", 9 | "serialNumber": "VCGE9KB041", 10 | "uuid": "1c5e807d-acbe-4ee8-868b-2fb0b6504474", 11 | "serverHardwareUri": "/rest/server-hardware/31363636-3136-584D-5132-333230314D38", 12 | "serverHardwareTypeUri": "/rest/server-hardware-types/2947DC35-BE48-4075-A3FD-254A9B42F5BD", 13 | "enclosureGroupUri": "/rest/enclosure-groups/3a11ccdd-b352-4046-a568-a8b0faa6cc39", 14 | "enclosureUri": "/rest/enclosures/09SGH236PMVW", 15 | "enclosureBay": 2, 16 | "affinity": "Bay", 17 | "associatedServer": null, 18 | "hideUnusedFlexNics": true, 19 | "firmware": { 20 | "forceInstallFirmware": false, 21 | "manageFirmware": true, 22 | "firmwareBaselineUri": "/rest/firmware-drivers/bp-hp-service-pack-for-proliant-oneview-2014-11-30-05" 23 | }, 24 | "macType": "Virtual", 25 | "wwnType": "Virtual", 26 | "serialNumberType": "Virtual", 27 | "category": "server-profiles", 28 | "created": "20150810T040139.738Z", 29 | "modified": "20150810T042450.221Z", 30 | "status": "OK", 31 | "state": "Normal", 32 | "inProgress": false, 33 | "taskUri": "/rest/tasks/2A17C3F9-6DBF-40B1-B99E-E8BA40848B40", 34 | "connections": [ 35 | { 36 | "id": 1, 37 | "name": "Altair PXE 1133", 38 | "functionType": "Ethernet", 39 | "deploymentStatus": "Deployed", 40 | "networkUri": "/rest/ethernet-networks/02b0b5c3-1a0a-4d5f-b5c9-0c7532cb1e5e", 41 | "portId": "Flb 1:1-a", 42 | "interconnectUri": "/rest/interconnects/34501559-719f-4393-9fb1-a43714037f06", 43 | "macType": "Virtual", 44 | "wwpnType": "Virtual", 45 | "mac": "11:11:11:11:01:14", 46 | "wwnn": null, 47 | "wwpn": null, 48 | "requestedMbps": "2500", 49 | "allocatedMbps": 2500, 50 | "maximumMbps": 10000, 51 | "boot": { 52 | "priority": "Primary" 53 | } 54 | }, 55 | { 56 | "id": 2, 57 | "name": "corpnet 10", 58 | "functionType": "Ethernet", 59 | "deploymentStatus": "Deployed", 60 | "networkUri": "/rest/ethernet-networks/7a4698ae-5933-4e2e-8af3-57893c23a2d2", 61 | "portId": "Flb 1:2-a", 62 | "interconnectUri": "/rest/interconnects/d6c76eb3-10e6-43bf-95a6-ec824dc7bb2e", 63 | "macType": "Virtual", 64 | "wwpnType": "Virtual", 65 | "mac": "11:11:11:11:01:15", 66 | "wwnn": null, 67 | "wwpn": null, 68 | "requestedMbps": "2500", 69 | "allocatedMbps": 2500, 70 | "maximumMbps": 10000, 71 | "boot": { 72 | "priority": "NotBootable" 73 | } 74 | } 75 | ], 76 | "bootMode": null, 77 | "boot": { 78 | "manageBoot": true, 79 | "order": [ 80 | "HardDisk", 81 | "PXE", 82 | "CD", 83 | "Floppy", 84 | "USB" 85 | ] 86 | }, 87 | "bios": { 88 | "manageBios": true, 89 | "overriddenSettings": [ 90 | { 91 | "id": "158", 92 | "value": "2" 93 | }, 94 | { 95 | "id": "181", 96 | "value": "1" 97 | }, 98 | { 99 | "id": "176", 100 | "value": "1" 101 | } 102 | ] 103 | }, 104 | "localStorage": { 105 | "logicalDrives": [ 106 | { 107 | "raidLevel": "RAID0", 108 | "bootable": true 109 | } 110 | ], 111 | "manageLocalStorage": true, 112 | "initialize": false 113 | }, 114 | "sanStorage": { 115 | "volumeAttachments": [ 116 | 117 | ], 118 | "manageSanStorage": false 119 | }, 120 | "eTag": "1439179303124/6" 121 | } 122 | ], 123 | "total": 1, 124 | "start": 0, 125 | "prevPageUri": null, 126 | "nextPageUri": null, 127 | "count": 1, 128 | "category": "server-profiles", 129 | "created": "20150810T223058.112Z", 130 | "eTag": "20150810T223058.112Z", 131 | "modified": "20150810T223058.112Z", 132 | "uri": "/rest/server-profiles?filter=name%20matches%20'chef-web01'&sort=name:asc" 133 | } 134 | -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v120/server-profiles_name_chef-web03.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "ServerProfileListV4", 3 | "members": [ 4 | { 5 | "type": "ServerProfileV4", 6 | "uri": "/rest/server-profiles/1c5e807d-acbe-4ee8-868b-2fb0b6504474", 7 | "name": "chef-web03", 8 | "description": "Web server machine template", 9 | "serialNumber": "VCGE9KB041", 10 | "uuid": "1c5e807d-acbe-4ee8-868b-2fb0b6504474", 11 | "serverHardwareUri": "/rest/server-hardware/31363636-3136-584D-5132-333230314D38", 12 | "serverHardwareTypeUri": "/rest/server-hardware-types/2947DC35-BE48-4075-A3FD-254A9B42F5BD", 13 | "enclosureGroupUri": "/rest/enclosure-groups/3a11ccdd-b352-4046-a568-a8b0faa6cc39", 14 | "enclosureUri": "/rest/enclosures/09SGH236PMVW", 15 | "enclosureBay": 2, 16 | "affinity": "Bay", 17 | "associatedServer": null, 18 | "hideUnusedFlexNics": true, 19 | "firmware": { 20 | "forceInstallFirmware": false, 21 | "manageFirmware": true, 22 | "firmwareBaselineUri": "/rest/firmware-drivers/bp-hp-service-pack-for-proliant-oneview-2014-11-30-05" 23 | }, 24 | "macType": "Virtual", 25 | "wwnType": "Virtual", 26 | "serialNumberType": "Virtual", 27 | "category": "server-profiles", 28 | "created": "20150810T040139.738Z", 29 | "modified": "20150810T042450.221Z", 30 | "status": "OK", 31 | "state": "Normal", 32 | "inProgress": false, 33 | "taskUri": "/rest/tasks/2A17C3F9-6DBF-40B1-B99E-E8BA40848B40", 34 | "connections": [ 35 | { 36 | "id": 1, 37 | "name": "Altair PXE 1133", 38 | "functionType": "Ethernet", 39 | "deploymentStatus": "Deployed", 40 | "networkUri": "/rest/ethernet-networks/02b0b5c3-1a0a-4d5f-b5c9-0c7532cb1e5e", 41 | "portId": "Flb 1:1-a", 42 | "interconnectUri": "/rest/interconnects/34501559-719f-4393-9fb1-a43714037f06", 43 | "macType": "Virtual", 44 | "wwpnType": "Virtual", 45 | "mac": "11:11:11:11:01:14", 46 | "wwnn": null, 47 | "wwpn": null, 48 | "requestedMbps": "2500", 49 | "allocatedMbps": 2500, 50 | "maximumMbps": 10000, 51 | "boot": { 52 | "priority": "Primary" 53 | } 54 | }, 55 | { 56 | "id": 2, 57 | "name": "corpnet 10", 58 | "functionType": "Ethernet", 59 | "deploymentStatus": "Deployed", 60 | "networkUri": "/rest/ethernet-networks/7a4698ae-5933-4e2e-8af3-57893c23a2d2", 61 | "portId": "Flb 1:2-a", 62 | "interconnectUri": "/rest/interconnects/d6c76eb3-10e6-43bf-95a6-ec824dc7bb2e", 63 | "macType": "Virtual", 64 | "wwpnType": "Virtual", 65 | "mac": "11:11:11:11:01:15", 66 | "wwnn": null, 67 | "wwpn": null, 68 | "requestedMbps": "2500", 69 | "allocatedMbps": 2500, 70 | "maximumMbps": 10000, 71 | "boot": { 72 | "priority": "NotBootable" 73 | } 74 | } 75 | ], 76 | "bootMode": null, 77 | "boot": { 78 | "manageBoot": true, 79 | "order": [ 80 | "HardDisk", 81 | "PXE", 82 | "CD", 83 | "Floppy", 84 | "USB" 85 | ] 86 | }, 87 | "bios": { 88 | "manageBios": true, 89 | "overriddenSettings": [ 90 | { 91 | "id": "158", 92 | "value": "2" 93 | }, 94 | { 95 | "id": "181", 96 | "value": "1" 97 | }, 98 | { 99 | "id": "176", 100 | "value": "1" 101 | } 102 | ] 103 | }, 104 | "localStorage": { 105 | "logicalDrives": [ 106 | { 107 | "raidLevel": "RAID0", 108 | "bootable": true 109 | } 110 | ], 111 | "manageLocalStorage": true, 112 | "initialize": false 113 | }, 114 | "sanStorage": { 115 | "volumeAttachments": [ 116 | 117 | ], 118 | "manageSanStorage": false 119 | }, 120 | "eTag": "1439179303124/6" 121 | } 122 | ], 123 | "total": 1, 124 | "start": 0, 125 | "prevPageUri": null, 126 | "nextPageUri": null, 127 | "count": 1, 128 | "category": "server-profiles", 129 | "created": "20150810T223058.112Z", 130 | "eTag": "20150810T223058.112Z", 131 | "modified": "20150810T223058.112Z", 132 | "uri": "/rest/server-profiles?filter=name%20matches%20'chef-web01'&sort=name:asc" 133 | } 134 | -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v120/server-profiles_sn_VCGE9KB041.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "ServerProfileListV4", 3 | "members": [ 4 | { 5 | "type": "ServerProfileV4", 6 | "uri": "/rest/server-profiles/1c5e807d-acbe-4ee8-868b-2fb0b6504474", 7 | "name": "chef-web01", 8 | "description": "Web server machine template", 9 | "serialNumber": "VCGE9KB041", 10 | "uuid": "1c5e807d-acbe-4ee8-868b-2fb0b6504474", 11 | "serverHardwareUri": "/rest/server-hardware/31363636-3136-584D-5132-333230314D38", 12 | "serverHardwareTypeUri": "/rest/server-hardware-types/2947DC35-BE48-4075-A3FD-254A9B42F5BD", 13 | "enclosureGroupUri": "/rest/enclosure-groups/3a11ccdd-b352-4046-a568-a8b0faa6cc39", 14 | "enclosureUri": "/rest/enclosures/09SGH236PMVW", 15 | "enclosureBay": 2, 16 | "affinity": "Bay", 17 | "associatedServer": null, 18 | "hideUnusedFlexNics": true, 19 | "firmware": { 20 | "forceInstallFirmware": false, 21 | "manageFirmware": true, 22 | "firmwareBaselineUri": "/rest/firmware-drivers/bp-hp-service-pack-for-proliant-oneview-2014-11-30-05" 23 | }, 24 | "macType": "Virtual", 25 | "wwnType": "Virtual", 26 | "serialNumberType": "Virtual", 27 | "category": "server-profiles", 28 | "created": "20150810T040139.738Z", 29 | "modified": "20150810T042450.221Z", 30 | "status": "OK", 31 | "state": "Normal", 32 | "inProgress": false, 33 | "taskUri": "/rest/tasks/2A17C3F9-6DBF-40B1-B99E-E8BA40848B40", 34 | "connections": [ 35 | { 36 | "id": 1, 37 | "name": "Altair PXE 1133", 38 | "functionType": "Ethernet", 39 | "deploymentStatus": "Deployed", 40 | "networkUri": "/rest/ethernet-networks/02b0b5c3-1a0a-4d5f-b5c9-0c7532cb1e5e", 41 | "portId": "Flb 1:1-a", 42 | "interconnectUri": "/rest/interconnects/34501559-719f-4393-9fb1-a43714037f06", 43 | "macType": "Virtual", 44 | "wwpnType": "Virtual", 45 | "mac": "11:11:11:11:01:14", 46 | "wwnn": null, 47 | "wwpn": null, 48 | "requestedMbps": "2500", 49 | "allocatedMbps": 2500, 50 | "maximumMbps": 10000, 51 | "boot": { 52 | "priority": "Primary" 53 | } 54 | }, 55 | { 56 | "id": 2, 57 | "name": "corpnet 10", 58 | "functionType": "Ethernet", 59 | "deploymentStatus": "Deployed", 60 | "networkUri": "/rest/ethernet-networks/7a4698ae-5933-4e2e-8af3-57893c23a2d2", 61 | "portId": "Flb 1:2-a", 62 | "interconnectUri": "/rest/interconnects/d6c76eb3-10e6-43bf-95a6-ec824dc7bb2e", 63 | "macType": "Virtual", 64 | "wwpnType": "Virtual", 65 | "mac": "11:11:11:11:01:15", 66 | "wwnn": null, 67 | "wwpn": null, 68 | "requestedMbps": "2500", 69 | "allocatedMbps": 2500, 70 | "maximumMbps": 10000, 71 | "boot": { 72 | "priority": "NotBootable" 73 | } 74 | } 75 | ], 76 | "bootMode": null, 77 | "boot": { 78 | "manageBoot": true, 79 | "order": [ 80 | "HardDisk", 81 | "PXE", 82 | "CD", 83 | "Floppy", 84 | "USB" 85 | ] 86 | }, 87 | "bios": { 88 | "manageBios": true, 89 | "overriddenSettings": [ 90 | { 91 | "id": "158", 92 | "value": "2" 93 | }, 94 | { 95 | "id": "181", 96 | "value": "1" 97 | }, 98 | { 99 | "id": "176", 100 | "value": "1" 101 | } 102 | ] 103 | }, 104 | "localStorage": { 105 | "logicalDrives": [ 106 | { 107 | "raidLevel": "RAID0", 108 | "bootable": true 109 | } 110 | ], 111 | "manageLocalStorage": true, 112 | "initialize": false 113 | }, 114 | "sanStorage": { 115 | "volumeAttachments": [ 116 | 117 | ], 118 | "manageSanStorage": false 119 | }, 120 | "eTag": "1439179303124/6" 121 | } 122 | ], 123 | "total": 1, 124 | "start": 0, 125 | "prevPageUri": null, 126 | "nextPageUri": null, 127 | "count": 1, 128 | "category": "server-profiles", 129 | "created": "20150810T223058.112Z", 130 | "eTag": "20150810T223058.112Z", 131 | "modified": "20150810T223058.112Z", 132 | "uri": "/rest/server-profiles?filter=serialNumber%20matches%20'VCGE9KB041'&sort=name:asc" 133 | } -------------------------------------------------------------------------------- /spec/support/fixtures/icsp/v102/os-deployment-build-plans.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "OsdPaginatedCollection", 3 | "members": [ 4 | { 5 | "modifiedBy": "applianceserviceaccount", 6 | "createdBy": "applianceserviceaccount", 7 | "buildPlanHistory": [], 8 | "buildPlanStepType": null, 9 | "isCustomerContent": true, 10 | "buildPlanCustAttrs": [], 11 | "buildPlanItems": [], 12 | "os": "OS - Red Hat Enterprise Linux Server 6", 13 | "arch": "x64", 14 | "lifeCycle": "AVAILABLE", 15 | "description": "Performs a scripted install of Red Hat Enterprise Linux 6.5 using a generic kickstart file.\n(c) Copyright 2014 Hewlett-Packard Development Company, L.P.\n\nRequirements:\n* HP ProLiant server with iLO\n* IC server provisioning Media Server must contain the OS distribution\n\nRequired Custom Attribute: None\n\nOptional Custom Attributes:\n* encrypted_root_password (must be encrypted)\n* boot_disk\n* kernel_arguments", 16 | "status": "", 17 | "name": "CHEF-RHEL-6.5-x64", 18 | "state": "", 19 | "modified": "2015-07-14T03:51:30.000Z", 20 | "eTag": "2015-07-14T03:51:30.000Z", 21 | "created": "2015-05-19T19:05:37.000Z", 22 | "category": "os-deployment-build-plans", 23 | "uri": "/rest/os-deployment-build-plans/1280001" 24 | }, 25 | { 26 | "modifiedBy": "applianceserviceaccount", 27 | "createdBy": "applianceserviceaccount", 28 | "buildPlanHistory": [], 29 | "buildPlanStepType": null, 30 | "isCustomerContent": true, 31 | "buildPlanCustAttrs": [], 32 | "buildPlanItems": [], 33 | "os": "Other", 34 | "arch": "x64", 35 | "lifeCycle": "AVAILABLE", 36 | "description": "Reboots a target server in maintenance mode to the local disk. \n(c) Copyright 2013 Hewlett-Packard Development Company, L.P.\n\nRequirements:\n* HP ProLiant server with iLO\n\nCustom Attributes: None", 37 | "status": "", 38 | "name": "CHEF - RHEL 6.6 x64", 39 | "state": "", 40 | "modified": "2015-05-21T17:23:58.000Z", 41 | "eTag": "2015-05-21T17:23:58.000Z", 42 | "created": "2015-05-21T17:23:58.000Z", 43 | "category": "os-deployment-build-plans", 44 | "uri": "/rest/os-deployment-build-plans/1300001" 45 | }, 46 | { 47 | "modifiedBy": "applianceserviceaccount", 48 | "createdBy": "applianceserviceaccount", 49 | "buildPlanHistory": [], 50 | "buildPlanStepType": null, 51 | "isCustomerContent": true, 52 | "buildPlanCustAttrs": [], 53 | "buildPlanItems": [], 54 | "os": "OS - Red Hat Enterprise Linux Server 7", 55 | "arch": "x64", 56 | "lifeCycle": "AVAILABLE", 57 | "description": "Performs a scripted install of Red Hat Enterprise Linux 7.0 using a generic kickstart file.\n(c) Copyright 2014 Hewlett-Packard Development Company, L.P.\n\nRequirements:\n* HP ProLiant server with iLO\n* IC server provisioning Media Server must contain the OS distribution\n\nRequired Custom Attribute: None\n\nOptional Custom Attributes:\n* encrypted_root_password (must be encrypted)\n* boot_disk\n* kernel_arguments", 58 | "status": "", 59 | "name": "CHEF - RHEL 7.0 x64", 60 | "state": "", 61 | "modified": "2015-07-24T09:32:52.000Z", 62 | "eTag": "2015-07-24T09:32:52.000Z", 63 | "created": "2015-07-15T17:46:32.000Z", 64 | "category": "os-deployment-build-plans", 65 | "uri": "/rest/os-deployment-build-plans/1340001" 66 | }, 67 | { 68 | "modifiedBy": "detuser", 69 | "createdBy": "opsware", 70 | "buildPlanHistory": [], 71 | "buildPlanStepType": null, 72 | "isCustomerContent": false, 73 | "buildPlanCustAttrs": [], 74 | "buildPlanItems": [], 75 | "os": "OS - Windows Server 2008 R2", 76 | "arch": "x64", 77 | "lifeCycle": "AVAILABLE", 78 | "description": "Performs a scripted install of Windows 2008 R2 SP1 Standard using a generic unattend file.\n(c) Copyright 2013, 2014 Hewlett-Packard Development Company, L.P.\n\nRequirements:\n* HP ProLiant server with iLO\n* IC server provisioning Media Server must contain the OS distribution\n\nRequired Custom Attribute:\n* ProductKey_Win2008R2-Std-x64 - Set using the Settings -> Product Key page.\n\nOptional Custom Attributes:\n* ComputerName\n* EncryptedAdminPassword (must be encrypted)\n* SystemDisk\n* SystemDiskNumber", 79 | "status": "", 80 | "name": "ProLiant OS - Windows 2008 R2 SP1 Standard x64 Scripted Install", 81 | "state": "", 82 | "modified": "2014-09-15T02:30:17.000Z", 83 | "eTag": "2014-09-15T02:30:17.000Z", 84 | "created": "2014-09-15T02:30:17.000Z", 85 | "category": "os-deployment-build-plans", 86 | "uri": "/rest/os-deployment-build-plans/1040001" 87 | } 88 | ], 89 | "start": 0, 90 | "prevPageUri": null, 91 | "nextPageUri": null, 92 | "total": 0, 93 | "count": 71, 94 | "modified": null, 95 | "eTag": null, 96 | "created": null, 97 | "category": null, 98 | "uri": null 99 | } 100 | -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v200/server-profile-templates_WebServerTemplateWithSAN.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "ServerProfileTemplateListV1", 3 | "members": [ 4 | { 5 | "type": "ServerProfileTemplateV1", 6 | "uri": "/rest/server-profile-templates/d64da635-f08a-41d4-b6eb-6517206a8baf", 7 | "name": "Web Server Template with SAN", 8 | "description": "", 9 | "serverProfileDescription": "Web Server Template with SAN", 10 | "serverHardwareTypeUri": "/rest/server-hardware-types/5B42EABE-5140-4E38-91F0-68367B529DE9", 11 | "enclosureGroupUri": "/rest/enclosure-groups/c0f86584-5a82-4480-ad13-8ed6544d6c98", 12 | "affinity": "Bay", 13 | "hideUnusedFlexNics": true, 14 | "macType": "Virtual", 15 | "wwnType": "Virtual", 16 | "serialNumberType": "Virtual", 17 | "firmware": { 18 | "manageFirmware": false, 19 | "firmwareInstallType": null, 20 | "forceInstallFirmware": false, 21 | "firmwareBaselineUri": null 22 | }, 23 | "connections": [ 24 | { 25 | "id": 7, 26 | "name": "Altair PXE", 27 | "functionType": "Ethernet", 28 | "networkUri": "/rest/ethernet-networks/7984a764-69ae-48c0-aec2-780d4f0366f8", 29 | "portId": "Flb 1:1-a", 30 | "requestedVFs": "Auto", 31 | "requestedMbps": "1000", 32 | "boot": { 33 | "priority": "Primary" 34 | } 35 | }, 36 | { 37 | "id": 8, 38 | "name": "Corpnet", 39 | "functionType": "Ethernet", 40 | "networkUri": "/rest/ethernet-networks/52b6f044-f51b-4d4c-8d59-497c14c4681c", 41 | "portId": "Flb 1:1-c", 42 | "requestedVFs": "Auto", 43 | "requestedMbps": "2500", 44 | "boot": { 45 | "priority": "NotBootable" 46 | } 47 | }, 48 | { 49 | "id": 9, 50 | "name": "san1", 51 | "functionType": "FibreChannel", 52 | "networkUri": "/rest/fc-networks/2c04a682-66b4-4a64-8c2d-3095937a8e7e", 53 | "portId": "Flb 1:1-b", 54 | "requestedVFs": null, 55 | "requestedMbps": "4000", 56 | "boot": { 57 | "priority": "Primary", 58 | "specifyBootTarget": false 59 | } 60 | }, 61 | { 62 | "id": 10, 63 | "name": "san2", 64 | "functionType": "FibreChannel", 65 | "networkUri": "/rest/fc-networks/93c97ad9-3e6d-4cc4-8b37-3ef3a6a9cf77", 66 | "portId": "Flb 1:2-b", 67 | "requestedVFs": null, 68 | "requestedMbps": "4000", 69 | "boot": { 70 | "priority": "Secondary", 71 | "specifyBootTarget": false 72 | } 73 | } 74 | ], 75 | "bootMode": null, 76 | "boot": { 77 | "manageBoot": true, 78 | "order": [ 79 | "HardDisk", 80 | "PXE", 81 | "CD", 82 | "Floppy", 83 | "USB" 84 | ] 85 | }, 86 | "bios": { 87 | "manageBios": false, 88 | "overriddenSettings": [ 89 | 90 | ] 91 | }, 92 | "localStorage": { 93 | "controllers": [] 94 | }, 95 | "sanStorage": { 96 | "manageSanStorage": true, 97 | "hostOSType": "RHE Linux (5.x, 6.x)", 98 | "volumeAttachments": [ 99 | { 100 | "id": 1, 101 | "lun": "0", 102 | "lunType": "Manual", 103 | "permanent": false, 104 | "storagePaths": [ 105 | { 106 | "connectionId": 9, 107 | "isEnabled": true, 108 | "storageTargetType": "Auto" 109 | }, 110 | { 111 | "connectionId": 10, 112 | "isEnabled": true, 113 | "storageTargetType": "Auto" 114 | } 115 | ], 116 | "volumeName": "bootVol", 117 | "volumeDescription": "", 118 | "volumeStoragePoolUri": "/rest/storage-pools/707E383B-56F6-48A1-BFF1-782BB2AC6BA7", 119 | "volumeProvisionedCapacityBytes": "53687091200", 120 | "volumeProvisionType": "Thin", 121 | "volumeShareable": false, 122 | "volumeStorageSystemUri": "/rest/storage-systems/1405534" 123 | } 124 | ] 125 | }, 126 | "category": "server-profile-templates", 127 | "created": "2015-09-04T17:15:39.249Z", 128 | "modified": "2015-09-04T17:41:44.999Z", 129 | "status": "OK", 130 | "state": null, 131 | "eTag": "1441388504999/3" 132 | } 133 | ], 134 | "nextPageUri": null, 135 | "start": 0, 136 | "prevPageUri": null, 137 | "total": 1, 138 | "count": 1, 139 | "modified": "2015-09-15T23:18:39.561Z", 140 | "eTag": "2015-09-15T23:18:39.561Z", 141 | "created": "2015-09-15T23:18:39.561Z", 142 | "category": "server-profile-templates", 143 | "uri": "/rest/server-profile-templates?filter=%22name%20matches%20'Web%20Server%20Template%20with%20SAN'%22&sort=name:asc&start=0&count=64" 144 | } 145 | -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v120/server-hardware_specific.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "server-hardware-3", 3 | "name": "dazzle, bay 2", 4 | "state": "ProfileApplied", 5 | "stateReason": "NotApplicable", 6 | "assetTag": "\n ", 7 | "category": "server-hardware", 8 | "created": "2015-07-02T16:24:23.447Z", 9 | "description": null, 10 | "eTag": "1439180722361", 11 | "formFactor": "HalfHeight", 12 | "licensingIntent": "OneViewNoiLO", 13 | "locationUri": "/rest/enclosures/09SGH236PMVW", 14 | "memoryMb": 16384, 15 | "model": "ProLiant BL460c Gen8", 16 | "modified": "2015-08-10T04:25:22.361Z", 17 | "mpDnsName": "ILOMAQ96601Z4", 18 | "mpFirmwareVersion": "2.10 Jan 15 2015", 19 | "mpIpAddress": "172.125.24.230", 20 | "mpModel": "iLO4", 21 | "partNumber": "666161-B21", 22 | "portMap": { 23 | "deviceSlots": [ 24 | { 25 | "deviceName": "HP FlexFabric 10Gb 2-port 554FLB Adapter", 26 | "location": "Flb", 27 | "oaSlotNumber": 9, 28 | "physicalPorts": [ 29 | { 30 | "interconnectPort": 2, 31 | "interconnectUri": "/rest/interconnects/34501559-719f-4393-9fb1-a43714037f06", 32 | "mac": "11:11:11:11:31:28", 33 | "portNumber": 1, 34 | "type": "Ethernet", 35 | "virtualPorts": [ 36 | { 37 | "mac": "11:11:11:11:01:14", 38 | "portFunction": "a", 39 | "portNumber": 1, 40 | "wwnn": null, 41 | "wwpn": null 42 | }, 43 | { 44 | "mac": "11:11:11:11:31:29", 45 | "portFunction": "b", 46 | "portNumber": 2, 47 | "wwnn": "11:11:11:11:11:11:11:11", 48 | "wwpn": "11:11:11:11:11:11:11:11" 49 | }, 50 | { 51 | "mac": "11:11:11:11:31:2A", 52 | "portFunction": "c", 53 | "portNumber": 3, 54 | "wwnn": null, 55 | "wwpn": null 56 | }, 57 | { 58 | "mac": "11:11:11:11:31:2B", 59 | "portFunction": "d", 60 | "portNumber": 4, 61 | "wwnn": null, 62 | "wwpn": null 63 | } 64 | ], 65 | "wwn": null 66 | }, 67 | { 68 | "interconnectPort": 2, 69 | "interconnectUri": "/rest/interconnects/d6c76eb3-10e6-43bf-95a6-ec824dc7bb2e", 70 | "mac": "11:11:11:11:31:2C", 71 | "portNumber": 2, 72 | "type": "Ethernet", 73 | "virtualPorts": [ 74 | { 75 | "mac": "11:11:11:11:01:15", 76 | "portFunction": "a", 77 | "portNumber": 1, 78 | "wwnn": null, 79 | "wwpn": null 80 | }, 81 | { 82 | "mac": "11:11:11:11:31:2D", 83 | "portFunction": "b", 84 | "portNumber": 2, 85 | "wwnn": "11:11:11:11:11:11:11:11", 86 | "wwpn": "11:11:11:11:11:11:11:11" 87 | }, 88 | { 89 | "mac": "11:11:11:11:31:2E", 90 | "portFunction": "c", 91 | "portNumber": 3, 92 | "wwnn": null, 93 | "wwpn": null 94 | }, 95 | { 96 | "mac": "11:11:11:11:31:2F", 97 | "portFunction": "d", 98 | "portNumber": 4, 99 | "wwnn": null, 100 | "wwpn": null 101 | } 102 | ], 103 | "wwn": null 104 | } 105 | ], 106 | "slotNumber": 1 107 | }, 108 | { 109 | "deviceName": "", 110 | "location": "Mezz", 111 | "oaSlotNumber": 1, 112 | "physicalPorts": [ 113 | 114 | ], 115 | "slotNumber": 1 116 | }, 117 | { 118 | "deviceName": "", 119 | "location": "Mezz", 120 | "oaSlotNumber": 2, 121 | "physicalPorts": [ 122 | 123 | ], 124 | "slotNumber": 2 125 | } 126 | ] 127 | }, 128 | "position": 2, 129 | "powerLock": false, 130 | "powerState": "Powering-On", 131 | "processorCoreCount": 6, 132 | "processorCount": 1, 133 | "processorSpeedMhz": 2000, 134 | "processorType": "Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00GHz", 135 | "refreshState": "NotRefreshing", 136 | "romVersion": "I31 11/02/2014", 137 | "serialNumber": "MAQ96601Z4", 138 | "serverGroupUri": "/rest/enclosure-groups/3a11ccdd-b352-4046-a568-a8b0faa6cc39", 139 | "serverHardwareTypeUri": "/rest/server-hardware-types/2947DC35-BE48-4075-A3FD-254A9B42F5BD", 140 | "serverProfileUri": "/rest/server-profiles/1c5e807d-acbe-4ee8-868b-2fb0b6504474", 141 | "shortModel": "BL460c Gen8", 142 | "signature": { 143 | "personalityChecksum": 2015957748, 144 | "serverHwChecksum": 508556751 145 | }, 146 | "status": "OK", 147 | "uri": "/rest/server-hardware/31363636-3136-584D-5132-333230314D38", 148 | "uuid": "31363636-3136-584D-5132-333230314D38", 149 | "virtualSerialNumber": "VCGE9KB041", 150 | "virtualUuid": "1c5e807d-acbe-4ee8-868b-2fb0b6504474" 151 | } -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v200/server-profile-templates_new-profile_WebServerTemplateWithSAN.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "ServerProfileV5", 3 | "uri": null, 4 | "name": null, 5 | "description": "Web server template with SAN", 6 | "serialNumber": null, 7 | "uuid": null, 8 | "serverProfileTemplateUri": "/rest/server-profile-templates/d64da635-f08a-41d4-b6eb-6517206a8baf", 9 | "templateCompliance": "Unknown", 10 | "serverHardwareUri": null, 11 | "serverHardwareTypeUri": "/rest/server-hardware-types/5B42EABE-5140-4E38-91F0-68367B529DE9", 12 | "enclosureGroupUri": "/rest/enclosure-groups/c0f86584-5a82-4480-ad13-8ed6544d6c98", 13 | "enclosureUri": null, 14 | "enclosureBay": null, 15 | "affinity": "Bay", 16 | "associatedServer": null, 17 | "hideUnusedFlexNics": true, 18 | "firmware": { 19 | "firmwareInstallType": null, 20 | "forceInstallFirmware": false, 21 | "manageFirmware": false, 22 | "firmwareBaselineUri": null 23 | }, 24 | "macType": "Virtual", 25 | "wwnType": "Virtual", 26 | "serialNumberType": "Virtual", 27 | "category": "server-profiles", 28 | "created": null, 29 | "modified": null, 30 | "status": "OK", 31 | "state": "Creating", 32 | "inProgress": false, 33 | "taskUri": null, 34 | "connections": [ 35 | { 36 | "id": 7, 37 | "name": "Altair PXE", 38 | "functionType": "Ethernet", 39 | "deploymentStatus": null, 40 | "networkUri": "/rest/ethernet-networks/7984a764-69ae-48c0-aec2-780d4f0366f8", 41 | "portId": "Flb 1:1-a", 42 | "requestedVFs": "Auto", 43 | "allocatedVFs": null, 44 | "interconnectUri": null, 45 | "macType": null, 46 | "wwpnType": null, 47 | "mac": null, 48 | "wwnn": null, 49 | "wwpn": null, 50 | "requestedMbps": "1000", 51 | "allocatedMbps": 0, 52 | "maximumMbps": 0, 53 | "boot": { 54 | "priority": "Primary" 55 | } 56 | }, 57 | { 58 | "id": 8, 59 | "name": "Corpnet", 60 | "functionType": "Ethernet", 61 | "deploymentStatus": null, 62 | "networkUri": "/rest/ethernet-networks/52b6f044-f51b-4d4c-8d59-497c14c4681c", 63 | "portId": "Flb 1:1-c", 64 | "requestedVFs": "Auto", 65 | "allocatedVFs": null, 66 | "interconnectUri": null, 67 | "macType": null, 68 | "wwpnType": null, 69 | "mac": null, 70 | "wwnn": null, 71 | "wwpn": null, 72 | "requestedMbps": "2500", 73 | "allocatedMbps": 0, 74 | "maximumMbps": 0, 75 | "boot": { 76 | "priority": "NotBootable" 77 | } 78 | }, 79 | { 80 | "id": 9, 81 | "name": "san1", 82 | "functionType": "FibreChannel", 83 | "deploymentStatus": null, 84 | "networkUri": "/rest/fc-networks/2c04a682-66b4-4a64-8c2d-3095937a8e7e", 85 | "portId": "Flb 1:1-b", 86 | "requestedVFs": null, 87 | "allocatedVFs": null, 88 | "interconnectUri": null, 89 | "macType": null, 90 | "wwpnType": null, 91 | "mac": null, 92 | "wwnn": null, 93 | "wwpn": null, 94 | "requestedMbps": "4000", 95 | "allocatedMbps": 0, 96 | "maximumMbps": 0, 97 | "boot": { 98 | "priority": "Primary" 99 | } 100 | }, 101 | { 102 | "id": 10, 103 | "name": "san2", 104 | "functionType": "FibreChannel", 105 | "deploymentStatus": null, 106 | "networkUri": "/rest/fc-networks/93c97ad9-3e6d-4cc4-8b37-3ef3a6a9cf77", 107 | "portId": "Flb 1:2-b", 108 | "requestedVFs": null, 109 | "allocatedVFs": null, 110 | "interconnectUri": null, 111 | "macType": null, 112 | "wwpnType": null, 113 | "mac": null, 114 | "wwnn": null, 115 | "wwpn": null, 116 | "requestedMbps": "4000", 117 | "allocatedMbps": 0, 118 | "maximumMbps": 0, 119 | "boot": { 120 | "priority": "Secondary" 121 | } 122 | } 123 | ], 124 | "bootMode": null, 125 | "boot": { 126 | "order": [ 127 | "HardDisk", 128 | "PXE", 129 | "CD", 130 | "Floppy", 131 | "USB" 132 | ], 133 | "manageBoot": true 134 | }, 135 | "bios": { 136 | "overriddenSettings": [ 137 | 138 | ], 139 | "manageBios": false 140 | }, 141 | "localStorage": { 142 | "controllers": [] 143 | }, 144 | "sanStorage": { 145 | "volumeAttachments": [ 146 | { 147 | "permanent": false, 148 | "storagePaths": [ 149 | { 150 | "storageTargets": [], 151 | "storageTargetType": "Auto", 152 | "connectionId": 3, 153 | "isEnabled": true 154 | }, 155 | { 156 | "storageTargets": [], 157 | "storageTargetType": "Auto", 158 | "connectionId": 4, 159 | "isEnabled": true 160 | } 161 | ], 162 | "volumeStoragePoolUri": "/rest/storage-pools/707E383B-56F6-48A1-BFF1-782BB2AC6BA7", 163 | "volumeStorageSystemUri": "/rest/storage-systems/1405534", 164 | "volumeDescription": "", 165 | "volumeShareable": false, 166 | "volumeProvisionType": "Thin", 167 | "volumeProvisionedCapacityBytes": "53687091200", 168 | "lun": "0", 169 | "lunType": "Manual", 170 | "volumeName": "bootVol", 171 | "id": 1 172 | } 173 | ], 174 | "hostOSType": "RHE Linux (5.x, 6.x)", 175 | "manageSanStorage": true 176 | }, 177 | "eTag": null 178 | } 179 | -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v200/server_profile_web01_with_san_unparsed.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "type": "ServerProfileV5", 4 | "uri": null, 5 | "name": "web01", 6 | "description": "Web server template with SAN", 7 | "serialNumber": null, 8 | "uuid": null, 9 | "serverProfileTemplateUri": "/rest/server-profile-templates/d64da635-f08a-41d4-b6eb-6517206a8baf", 10 | "templateCompliance": "Unknown", 11 | "serverHardwareUri": null, 12 | "serverHardwareTypeUri": "/rest/server-hardware-types/5B42EABE-5140-4E38-91F0-68367B529DE9", 13 | "enclosureGroupUri": "/rest/enclosure-groups/c0f86584-5a82-4480-ad13-8ed6544d6c98", 14 | "enclosureUri": null, 15 | "enclosureBay": null, 16 | "affinity": "Bay", 17 | "associatedServer": null, 18 | "hideUnusedFlexNics": true, 19 | "firmware": { 20 | "firmwareInstallType": null, 21 | "forceInstallFirmware": false, 22 | "manageFirmware": false, 23 | "firmwareBaselineUri": null 24 | }, 25 | "macType": "Virtual", 26 | "wwnType": "Virtual", 27 | "serialNumberType": "Virtual", 28 | "category": "server-profiles", 29 | "created": null, 30 | "modified": null, 31 | "status": "OK", 32 | "state": "Creating", 33 | "inProgress": false, 34 | "taskUri": null, 35 | "connections": [ 36 | { 37 | "id": 1, 38 | "name": "Altair PXE", 39 | "functionType": "Ethernet", 40 | "deploymentStatus": null, 41 | "networkUri": "/rest/ethernet-networks/7984a764-69ae-48c0-aec2-780d4f0366f8", 42 | "portId": "Flb 1:1-a", 43 | "requestedVFs": "Auto", 44 | "allocatedVFs": null, 45 | "interconnectUri": null, 46 | "macType": null, 47 | "wwpnType": null, 48 | "mac": null, 49 | "wwnn": null, 50 | "wwpn": null, 51 | "requestedMbps": "1000", 52 | "allocatedMbps": 0, 53 | "maximumMbps": 0, 54 | "boot": { 55 | "priority": "Primary" 56 | } 57 | }, 58 | { 59 | "id": 2, 60 | "name": "Corpnet", 61 | "functionType": "Ethernet", 62 | "deploymentStatus": null, 63 | "networkUri": "/rest/ethernet-networks/52b6f044-f51b-4d4c-8d59-497c14c4681c", 64 | "portId": "Flb 1:1-c", 65 | "requestedVFs": "Auto", 66 | "allocatedVFs": null, 67 | "interconnectUri": null, 68 | "macType": null, 69 | "wwpnType": null, 70 | "mac": null, 71 | "wwnn": null, 72 | "wwpn": null, 73 | "requestedMbps": "2500", 74 | "allocatedMbps": 0, 75 | "maximumMbps": 0, 76 | "boot": { 77 | "priority": "NotBootable" 78 | } 79 | }, 80 | { 81 | "id": 3, 82 | "name": "san1", 83 | "functionType": "FibreChannel", 84 | "deploymentStatus": null, 85 | "networkUri": "/rest/fc-networks/2c04a682-66b4-4a64-8c2d-3095937a8e7e", 86 | "portId": "Flb 1:1-b", 87 | "requestedVFs": null, 88 | "allocatedVFs": null, 89 | "interconnectUri": null, 90 | "macType": null, 91 | "wwpnType": null, 92 | "mac": null, 93 | "wwnn": null, 94 | "wwpn": null, 95 | "requestedMbps": "4000", 96 | "allocatedMbps": 0, 97 | "maximumMbps": 0, 98 | "boot": { 99 | "priority": "Primary" 100 | } 101 | }, 102 | { 103 | "id": 4, 104 | "name": "san2", 105 | "functionType": "FibreChannel", 106 | "deploymentStatus": null, 107 | "networkUri": "/rest/fc-networks/93c97ad9-3e6d-4cc4-8b37-3ef3a6a9cf77", 108 | "portId": "Flb 1:2-b", 109 | "requestedVFs": null, 110 | "allocatedVFs": null, 111 | "interconnectUri": null, 112 | "macType": null, 113 | "wwpnType": null, 114 | "mac": null, 115 | "wwnn": null, 116 | "wwpn": null, 117 | "requestedMbps": "4000", 118 | "allocatedMbps": 0, 119 | "maximumMbps": 0, 120 | "boot": { 121 | "priority": "Secondary" 122 | } 123 | } 124 | ], 125 | "bootMode": null, 126 | "boot": { 127 | "order": [ 128 | "HardDisk", 129 | "PXE", 130 | "CD", 131 | "Floppy", 132 | "USB" 133 | ], 134 | "manageBoot": true 135 | }, 136 | "bios": { 137 | "overriddenSettings": [ 138 | 139 | ], 140 | "manageBios": false 141 | }, 142 | "localStorage": { 143 | "controllers": [] 144 | }, 145 | "sanStorage": { 146 | "volumeAttachments": [ 147 | { 148 | "permanent": false, 149 | "storagePaths": [ 150 | { 151 | "storageTargets": [], 152 | "storageTargetType": "Auto", 153 | "connectionId": 3, 154 | "isEnabled": true 155 | }, 156 | { 157 | "storageTargets": [], 158 | "storageTargetType": "Auto", 159 | "connectionId": 4, 160 | "isEnabled": true 161 | } 162 | ], 163 | "volumeStoragePoolUri": "/rest/storage-pools/707E383B-56F6-48A1-BFF1-782BB2AC6BA7", 164 | "volumeStorageSystemUri": "/rest/storage-systems/1405534", 165 | "volumeDescription": "", 166 | "volumeShareable": false, 167 | "volumeProvisionType": "Thin", 168 | "volumeProvisionedCapacityBytes": "53687091200", 169 | "lun": "0", 170 | "lunType": "Manual", 171 | "volumeName": "boot", 172 | "id": 1 173 | } 174 | ], 175 | "hostOSType": "RHE Linux (5.x, 6.x)", 176 | "manageSanStorage": true 177 | }, 178 | "eTag": null 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /spec/support/fixtures/icsp/v102/os-deployment-servers.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "OsdPaginatedCollection", 3 | "members": [ 4 | { 5 | "modified": "2015-08-10T16:45:57.019Z", 6 | "deviceGroups": null, 7 | "customAttributes": [], 8 | "created": "2015-08-10T04:35:52.000Z", 9 | "uuid": "2b4e5e6c-6154-7849-9807-c96a7e0d445b", 10 | "cpus": [ 11 | { 12 | "cacheSize": "15360", 13 | "speed": "1200", 14 | "stepping": "7", 15 | "model": "Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00GHz", 16 | "family": "X64", 17 | "status": "ON-LINE", 18 | "slot": "0" 19 | } 20 | ], 21 | "ilo": null, 22 | "serverLocation": { 23 | "rack": "DemoRack", 24 | "enclosure": "dazzle", 25 | "bay": "3" 26 | }, 27 | "operatingSystemVersion": null, 28 | "opswLifecycle": "MANAGED", 29 | "osSPVersion": null, 30 | "peerIP": "192.168.133.41", 31 | "stage": "UNKNOWN", 32 | "running": "false", 33 | "reporting": true, 34 | "storageDevices": [], 35 | "ram": "16291780", 36 | "swap": "8216568", 37 | "architecture": null, 38 | "defaultGateway": "172.125.32.1", 39 | "discoveredDate": "2015-08-10T04:35:52.000Z", 40 | "facility": "Appliance", 41 | "hardwareModel": "PROLIANT BL460C GEN8", 42 | "jobsHistory": null, 43 | "lastScannedDate": null, 44 | "loopbackIP": null, 45 | "managementIP": "192.168.133.41", 46 | "manufacturer": "HP", 47 | "mid": "1680001", 48 | "netBios": null, 49 | "operatingSystem": null, 50 | "osFlavor": null, 51 | "serialNumber": "VCGE9KB035", 52 | "locale": null, 53 | "description": null, 54 | "status": "OK", 55 | "uri": "/rest/os-deployment-servers/1680001", 56 | "name": "chef-web02.domain.com", 57 | "interfaces": [ 58 | { 59 | "speed": "10000", 60 | "netmask": "255.255.254.0", 61 | "duplex": "FULL", 62 | "ipv6Addr": "", 63 | "macAddr": "11:11:11:11:01:17", 64 | "dhcpEnabled": false, 65 | "ipv4Addr": "172.125.32.39", 66 | "type": "ETHERNET", 67 | "slot": "eth1" 68 | }, 69 | { 70 | "speed": "10000", 71 | "netmask": "255.255.255.0", 72 | "duplex": "FULL", 73 | "ipv6Addr": "", 74 | "macAddr": "11:11:11:11:01:16", 75 | "dhcpEnabled": true, 76 | "ipv4Addr": "192.168.133.41", 77 | "type": "ETHERNET", 78 | "slot": "eth0" 79 | } 80 | ], 81 | "state": "OK", 82 | "hostName": "chef-web02.domain.com", 83 | "eTag": "2015-08-10T16:45:57.019Z", 84 | "category": "os-deployment-servers" 85 | }, 86 | { 87 | "modified": "2015-08-10T04:55:27.017Z", 88 | "deviceGroups": null, 89 | "customAttributes": [], 90 | "created": "2015-08-10T04:35:40.000Z", 91 | "uuid": "7d805e1c-beac-e84e-868b-2fb0b6504474", 92 | "cpus": [ 93 | { 94 | "cacheSize": "15360", 95 | "speed": "1200", 96 | "stepping": "7", 97 | "model": "Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00GHz", 98 | "family": "X64", 99 | "status": "ON-LINE", 100 | "slot": "0" 101 | } 102 | ], 103 | "ilo": null, 104 | "serverLocation": { 105 | "rack": "DemoRack", 106 | "enclosure": "dazzle", 107 | "bay": "2" 108 | }, 109 | "operatingSystemVersion": null, 110 | "opswLifecycle": "MANAGED", 111 | "osSPVersion": null, 112 | "peerIP": "192.168.133.36", 113 | "stage": "UNKNOWN", 114 | "running": "false", 115 | "reporting": true, 116 | "storageDevices": [], 117 | "ram": "16291780", 118 | "swap": "8216568", 119 | "architecture": null, 120 | "defaultGateway": "172.125.32.1", 121 | "discoveredDate": "2015-08-10T04:35:39.000Z", 122 | "facility": "Appliance", 123 | "hardwareModel": "PROLIANT BL460C GEN8", 124 | "jobsHistory": null, 125 | "lastScannedDate": null, 126 | "loopbackIP": null, 127 | "managementIP": "192.168.133.36", 128 | "manufacturer": "HP", 129 | "mid": "1670001", 130 | "netBios": null, 131 | "operatingSystem": null, 132 | "osFlavor": null, 133 | "serialNumber": "VCGE9KB041", 134 | "locale": null, 135 | "description": null, 136 | "status": "OK", 137 | "uri": "/rest/os-deployment-servers/1670001", 138 | "name": "chef-web01.domain.com", 139 | "interfaces": [ 140 | { 141 | "speed": "10000", 142 | "netmask": "255.255.254.0", 143 | "duplex": "FULL", 144 | "ipv6Addr": "", 145 | "macAddr": "11:11:11:11:01:15", 146 | "dhcpEnabled": false, 147 | "ipv4Addr": "172.125.32.38", 148 | "type": "ETHERNET", 149 | "slot": "eth1" 150 | }, 151 | { 152 | "speed": "10000", 153 | "netmask": "255.255.255.0", 154 | "duplex": "FULL", 155 | "ipv6Addr": "", 156 | "macAddr": "11:11:11:11:01:14", 157 | "dhcpEnabled": true, 158 | "ipv4Addr": "192.168.133.36", 159 | "type": "ETHERNET", 160 | "slot": "eth0" 161 | } 162 | ], 163 | "state": "OK", 164 | "hostName": "chef-web01.domain.com", 165 | "eTag": "2015-08-10T04:55:27.017Z", 166 | "category": "os-deployment-servers" 167 | } 168 | ], 169 | "start": 0, 170 | "prevPageUri": null, 171 | "nextPageUri": null, 172 | "total": 2, 173 | "count": 2, 174 | "modified": null, 175 | "eTag": null, 176 | "created": null, 177 | "category": null, 178 | "uri": null 179 | } -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v120/server_profile_web01_with_san_unparsed.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "type": "ServerProfileV4", 4 | "uri": null, 5 | "name": "web01", 6 | "description": "Web server machine with SAN", 7 | "serialNumber": "VCGE9KB035", 8 | "uuid": "a16654c6-d12d-4e42-aa04-8868cf3dc31a", 9 | "serverHardwareUri": null, 10 | "serverHardwareTypeUri": "/rest/server-hardware-types/2947DC35-BE48-4075-A3FD-254A9B42F5BD", 11 | "enclosureGroupUri": "/rest/enclosure-groups/3a11ccdd-b352-4046-a568-a8b0faa6cc39", 12 | "enclosureUri": null, 13 | "enclosureBay": null, 14 | "affinity": "Bay", 15 | "associatedServer": null, 16 | "hideUnusedFlexNics": true, 17 | "firmware": { 18 | "forceInstallFirmware": false, 19 | "manageFirmware": true, 20 | "firmwareBaselineUri": "/rest/firmware-drivers/bp-hp-service-pack-for-proliant-oneview-2014-11-30-05" 21 | }, 22 | "macType": "Virtual", 23 | "wwnType": "Virtual", 24 | "serialNumberType": "Virtual", 25 | "category": "server-profiles", 26 | "created": "20150730T115836.727Z", 27 | "modified": "20150807T051446.275Z", 28 | "status": "OK", 29 | "state": "Normal", 30 | "inProgress": false, 31 | "taskUri": null, 32 | "connections": [ 33 | { 34 | "id": 1, 35 | "name": "Altair PXE 1133", 36 | "functionType": "Ethernet", 37 | "deploymentStatus": null, 38 | "networkUri": "/rest/ethernet-networks/02b0b5c3-1a0a-4d5f-b5c9-0c7532cb1e5e", 39 | "portId": "Flb 1:1-a", 40 | "interconnectUri": null, 41 | "macType": null, 42 | "wwpnType": null, 43 | "mac": null, 44 | "wwnn": null, 45 | "wwpn": null, 46 | "requestedMbps": "2500", 47 | "allocatedMbps": 2500, 48 | "maximumMbps": 10000, 49 | "boot": { 50 | "priority": "Primary" 51 | } 52 | }, 53 | { 54 | "id": 2, 55 | "name": "corpnet 10", 56 | "functionType": "Ethernet", 57 | "deploymentStatus": null, 58 | "networkUri": "/rest/ethernet-networks/7a4698ae-5933-4e2e-8af3-57893c23a2d2", 59 | "portId": "Flb 1:2-a", 60 | "interconnectUri": null, 61 | "macType": null, 62 | "wwpnType": null, 63 | "mac": null, 64 | "wwnn": null, 65 | "wwpn": null, 66 | "requestedMbps": "2500", 67 | "allocatedMbps": 2500, 68 | "maximumMbps": 10000, 69 | "boot": { 70 | "priority": "NotBootable" 71 | } 72 | }, 73 | { 74 | "id": 3, 75 | "name": "san1", 76 | "functionType": "FibreChannel", 77 | "deploymentStatus": null, 78 | "networkUri": "/rest/fc-networks/2c04a682-66b4-4a64-8c2d-3095937a8e7e", 79 | "portId": "Flb 1:1-b", 80 | "interconnectUri": null, 81 | "macType": null, 82 | "wwpnType": null, 83 | "mac": null, 84 | "wwnn": null, 85 | "wwpn": null, 86 | "requestedMbps": "4000", 87 | "allocatedMbps": 4000, 88 | "maximumMbps": 4000, 89 | "boot": { 90 | "priority": "Primary", 91 | "targets": [{ "arrayWwpn": "20540002AC00159E", "lun": "0" }] 92 | } 93 | }, 94 | { 95 | "id": 4, 96 | "name": "san2", 97 | "functionType": "FibreChannel", 98 | "deploymentStatus": null, 99 | "networkUri": "/rest/fc-networks/93c97ad9-3e6d-4cc4-8b37-3ef3a6a9cf77", 100 | "portId": "Flb 1:2-b", 101 | "interconnectUri": null, 102 | "macType": null, 103 | "wwpnType": null, 104 | "mac": null, 105 | "wwnn": null, 106 | "wwpn": null, 107 | "requestedMbps": "4000", 108 | "allocatedMbps": 4000, 109 | "maximumMbps": 4000, 110 | "boot": { 111 | "priority": "Secondary", 112 | "targets": [{ "arrayWwpn": "21210002AC00159F", "lun": "0" }] 113 | } 114 | } 115 | ], 116 | "bootMode": null, 117 | "boot": { 118 | "manageBoot": true, 119 | "order": [ 120 | "HardDisk", 121 | "PXE", 122 | "CD", 123 | "Floppy", 124 | "USB" 125 | ] 126 | }, 127 | "bios": { 128 | "manageBios": true, 129 | "overriddenSettings": [ 130 | { 131 | "id": "176", 132 | "value": "1" 133 | }, 134 | { 135 | "id": "181", 136 | "value": "1" 137 | }, 138 | { 139 | "id": "158", 140 | "value": "2" 141 | } 142 | ] 143 | }, 144 | "localStorage": { 145 | "manageLocalStorage": false, 146 | "initialize": false, 147 | "logicalDrives": null 148 | }, 149 | "sanStorage": { 150 | "volumeAttachments": [ 151 | { 152 | "storagePaths": [ 153 | { 154 | "storageTargets": [ 155 | "21:21:00:02:AC:00:15:9E" 156 | ], 157 | "storageTargetType": "Auto", 158 | "connectionId": 4, 159 | "isEnabled": true, 160 | "status": "OK" 161 | }, 162 | { 163 | "storageTargets": [ 164 | "20:54:00:02:AC:00:15:9E" 165 | ], 166 | "storageTargetType": "Auto", 167 | "connectionId": 3, 168 | "isEnabled": true, 169 | "status": "OK" 170 | } 171 | ], 172 | "state": "Attached", 173 | "volumeStoragePoolUri": "/rest/storage-pools/707E383B-56F6-48A1-BFF1-782BB2AC6BA7", 174 | "volumeStorageSystemUri": "/rest/storage-systems/1405534", 175 | "lun": "0", 176 | "lunType": "Manual", 177 | "volumeUri": "/rest/storage-volumes/1B5D3CA2-6C5B-41C2-8B97-1821F1883F22", 178 | "status": "OK", 179 | "id": 1 180 | } 181 | ], 182 | "hostOSType": "RHE Linux (5.x, 6.x)", 183 | "manageSanStorage": true 184 | }, 185 | "eTag": "1438924486161/12" 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /spec/support/fake_oneview.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra/base' 2 | require 'json' 3 | 4 | class FakeOneView < Sinatra::Base 5 | 6 | get '/rest/version' do 7 | json_response(200, 'version.json', '120') 8 | end 9 | 10 | post '/rest/login-sessions' do 11 | version = env['HTTP_X_API_VERSION'] 12 | json_response(200, 'login.json', version) 13 | end 14 | 15 | get '/rest/server-profile-templates' do 16 | version = env['HTTP_X_API_VERSION'] 17 | file_name = 'server-profile-templates_invalid.json' 18 | if params['filter'] && params['filter'] =~ /name matches/ 19 | if params['filter'] =~ /Web Server Template with SAN/ 20 | file_name = 'server-profile-templates_WebServerTemplateWithSAN.json' 21 | elsif params['filter'] =~ /Web Server Template/ 22 | file_name = 'server-profile-templates_WebServerTemplate.json' 23 | end 24 | end 25 | json_response(200, file_name, version) 26 | end 27 | 28 | get '/rest/server-profile-templates/:id/new-profile' do |id| 29 | version = env['HTTP_X_API_VERSION'] 30 | if id == 'd64da635-f08a-41d4-b6eb-6517206a8bae' 31 | json_response(200, 'server-profile-templates_new-profile_WebServerTemplate.json', version) 32 | elsif id == 'd64da635-f08a-41d4-b6eb-6517206a8baf' 33 | json_response(200, 'server-profile-templates_new-profile_WebServerTemplateWithSAN.json', version) 34 | else 35 | json_response(404, 'error_404.json', '120') 36 | end 37 | end 38 | 39 | get '/rest/server-profiles' do 40 | version = env['HTTP_X_API_VERSION'] 41 | file_name = 'server-profiles.json' 42 | if params['filter'] 43 | if params['filter'].match('matches \'\'') || params['filter'] =~ /INVALIDFILTER/ 44 | file_name = 'server-profiles_invalid_filter.json' 45 | elsif params['filter'] =~ /serialNumber matches/ 46 | file_name = if params['filter'] =~ /VCGE9KB041/ 47 | 'server-profiles_sn_VCGE9KB041.json' 48 | elsif params['filter'] =~ /VCGE9KB042/ 49 | 'server-profiles_sn_VCGE9KB042.json' 50 | else 51 | 'server-profiles_sn_empty.json' 52 | end 53 | elsif params['filter'] =~ /name matches/ 54 | file_name = if params['filter'] =~ /Template - Web Server with SAN/ 55 | 'server-profiles_name_Template-WebServerWithSAN.json' 56 | elsif params['filter'] =~ /Template - Web Server/ 57 | 'server-profiles_name_Template-WebServer.json' 58 | elsif params['filter'] =~ /chef-web01/ 59 | 'server-profiles_name_chef-web01.json' 60 | elsif $server_created == 'chef-web03' 61 | 'server-profiles_name_chef-web03.json' 62 | else 63 | 'server-profiles_name_empty.json' 64 | end 65 | end 66 | end 67 | json_response(200, file_name, version) 68 | end 69 | 70 | post '/rest/server-profiles' do 71 | body = JSON.parse(request.body.read.to_s) 72 | $server_created = body['name'] 73 | { 'uri' => '/rest/tasks/FAKETASK' }.to_json 74 | end 75 | 76 | delete '/rest/server-profiles/:id' do |_id| 77 | { 'uri' => '/rest/tasks/FAKETASK' }.to_json 78 | end 79 | 80 | get '/rest/server-hardware' do 81 | version = env['HTTP_X_API_VERSION'] 82 | file_name = 'server-hardware.json' 83 | if params['filter'] =~ %r{enclosure-groups/3a11ccdd-b352-4046-a568-a8b0faa6cc39} 84 | file_name = 'server-hardware_Template-WebServer.json' 85 | end 86 | json_response(200, file_name, version) 87 | end 88 | 89 | get '/rest/server-hardware/:id' do |id| 90 | version = env['HTTP_X_API_VERSION'] 91 | if id == '31363636-3136-584D-5132-333230314D38' || id == '37333036-3831-584D-5131-303030323037' 92 | json_response(200, 'server-hardware_specific.json', version) 93 | else 94 | json_response(404, 'error_404.json', '120') 95 | end 96 | end 97 | 98 | get '/rest/storage-volumes/:id' do |id| 99 | version = env['HTTP_X_API_VERSION'] 100 | json_response(200, "storage-volumes_#{id}.json", version) 101 | end 102 | 103 | put '/rest/server-hardware/:id/powerState' do |_id| 104 | { 'uri' => '/rest/tasks/FAKETASK' }.to_json 105 | end 106 | 107 | get '/rest/tasks/FAKETASK' do 108 | version = env['HTTP_X_API_VERSION'] 109 | json_response(200, 'tasks_fake_complete.json', version) 110 | end 111 | 112 | get '/' do 113 | { message: 'Fake OneView works!', method: env['REQUEST_METHOD'], content_type: env['CONTENT_TYPE'], query: env['QUERY_STRING'], 114 | api_version: env['HTTP_X_API_VERSION'], auth: env['HTTP_AUTH'], params: params }.to_json 115 | end 116 | 117 | post '/' do 118 | { message: 'Fake OneView works!', method: env['REQUEST_METHOD'], content_type: env['CONTENT_TYPE'], query: env['QUERY_STRING'], 119 | api_version: env['HTTP_X_API_VERSION'], auth: env['HTTP_AUTH'], params: params }.to_json 120 | end 121 | 122 | put '/' do 123 | { message: 'Fake OneView works!', method: env['REQUEST_METHOD'], content_type: env['CONTENT_TYPE'], query: env['QUERY_STRING'], 124 | api_version: env['HTTP_X_API_VERSION'], auth: env['HTTP_AUTH'], params: params }.to_json 125 | end 126 | 127 | delete '/' do 128 | { message: 'Fake OneView works!', method: env['REQUEST_METHOD'], content_type: env['CONTENT_TYPE'], query: env['QUERY_STRING'], 129 | api_version: env['HTTP_X_API_VERSION'], auth: env['HTTP_AUTH'], params: params }.to_json 130 | end 131 | 132 | get '/*' do # All other paths should return a 404 error 133 | json_response(404, 'error_404.json', '120') 134 | end 135 | 136 | private 137 | 138 | def json_response(response_code, file_name, version = 120) 139 | content_type :json 140 | status response_code 141 | File.open(File.dirname(__FILE__) + "/fixtures/oneview/v#{version}/" + file_name, 'rb').read 142 | rescue Errno::ENOENT 143 | puts "ERROR: FakeOneView: File not found:\n '#{File.dirname(__FILE__) + "/fixtures/oneview/v#{version}/" + file_name}'" 144 | content_type :json 145 | status 404 146 | File.open(File.dirname(__FILE__) + '/fixtures/oneview/v120/error_404.json', 'rb').read 147 | end 148 | end 149 | -------------------------------------------------------------------------------- /spec/unit/oneview_san_spec.rb: -------------------------------------------------------------------------------- 1 | require_relative './../spec_helper' 2 | 3 | RSpec.describe Chef::Provisioning::OneViewDriver do 4 | include_context 'shared context' 5 | 6 | let(:vol_details) do 7 | { 8 | 'name' => 'boot', 9 | 'isPermanent' => false, 10 | 'shareable' => false, 11 | 'provisionType' => 'Thin', 12 | 'provisionedCapacity' => '100000', 13 | 'description' => 'fakeDescription' 14 | } 15 | end 16 | 17 | describe '#fill_volume_details' do 18 | it 'fills the correct volume details' do 19 | v = { 'name' => 'old', 'volumeUri' => '/rest/fake' } 20 | expect(@ov_200).to receive(:rest_get).with('/rest/fake').and_return(FakeResponse.new(vol_details)) 21 | res = @driver_200.instance_eval { fill_volume_details(v) } 22 | expect(res).to eq(v) 23 | expect(v['volumeName']).to eq(vol_details['name']) 24 | expect(v['permanent']).to eq(vol_details['isPermanent']) 25 | expect(v['volumeShareable']).to eq(vol_details['shareable']) 26 | expect(v['volumeProvisionType']).to eq(vol_details['provisionType']) 27 | expect(v['volumeProvisionedCapacityBytes']).to eq(vol_details['provisionedCapacity']) 28 | expect(v['volumeDescription']).to eq(vol_details['description']) 29 | end 30 | end 31 | 32 | describe '#update_san_info' do 33 | before :each do 34 | allow_any_instance_of(OneviewSDK::Client).to receive(:rest_get).with(%r{/rest/storage-volumes/}).and_return(FakeResponse.new(vol_details)) 35 | end 36 | 37 | let(:profile_120) do 38 | 'spec/support/fixtures/oneview/v120/server_profile_web01_with_san_unparsed.json' 39 | end 40 | 41 | let(:profile_200) do 42 | 'spec/support/fixtures/oneview/v200/server_profile_web01_with_san_unparsed.json' 43 | end 44 | 45 | context 'profile coppies (OV 1.2)' do 46 | it 'prepares copies of profiles for SAN storage' do 47 | profile = OneviewSDK::ServerProfile.from_file(@ov_120, profile_120) 48 | m = machine_spec.name 49 | ret_val = @driver_120.instance_eval { update_san_info(m, profile) } 50 | v = ret_val['sanStorage']['volumeAttachments'].first 51 | expect(v['uri']).to be_nil 52 | expect(v['volumeName']).to eq('boot web01') 53 | expect(v['lun']).to eq('0') 54 | end 55 | end 56 | 57 | context 'Server Profile Templates (OV 2.0)' do 58 | it 'leaves profiles from Templates largely the same' do 59 | m = machine_spec.name 60 | profile = OneviewSDK::ServerProfile.from_file(@ov_200, profile_200) 61 | ret_val = @driver_200.instance_eval { update_san_info(m, profile) } 62 | expect(ret_val['sanStorage']['volumeAttachments'].first['storagePaths'].first.key?('state')).to be false 63 | end 64 | 65 | it 'appends the profile name to the volume name' do 66 | m = machine_spec.name 67 | profile = OneviewSDK::ServerProfile.from_file(@ov_200, profile_200) 68 | ret_val = @driver_200.instance_eval { update_san_info(m, profile) } 69 | v = ret_val['sanStorage']['volumeAttachments'].first 70 | expect(v['volumeName']).to eq('boot web01') 71 | end 72 | 73 | it 'requires profiles to specify the volumeShareable attribute' do 74 | m = machine_spec.name 75 | profile = OneviewSDK::ServerProfile.from_file(@ov_200, profile_200) 76 | profile['sanStorage']['volumeAttachments'].first.delete('volumeShareable') 77 | expect { @driver_200.instance_eval { update_san_info(m, profile) } }.to raise_error(/Should know if volume is sharable/) 78 | end 79 | 80 | it 'only allows 1 SAN boot volume' do 81 | m = machine_spec.name 82 | profile = OneviewSDK::ServerProfile.from_file(@ov_200, profile_200) 83 | profile['sanStorage']['volumeAttachments'].push('id' => 2, 'volumeName' => 'bootVol2', 'volumeShareable' => true) 84 | expect { @driver_200.instance_eval { update_san_info(m, profile) } }.to raise_error(/should only be 1 SAN boot volume/) 85 | end 86 | end 87 | end 88 | 89 | describe '#enable_boot_from_san' do 90 | before :each do 91 | allow_any_instance_of(OneviewSDK::Client).to receive(:rest_get).with(%r{/rest/storage-volumes/}).and_return(FakeResponse.new(vol_details)) 92 | end 93 | 94 | let(:profile_120) do 95 | 'spec/support/fixtures/oneview/v120/server_profile_web01_with_san.json' 96 | end 97 | 98 | it 'configures connections to boot from a SAN volume' do 99 | a = action_handler 100 | m = machine_spec.name 101 | profile = OneviewSDK::ServerProfile.from_file(@ov_120, profile_120) 102 | profile['connections'].each { |c| c['boot'].delete('targets') } 103 | expect_any_instance_of(OneviewSDK::ServerHardware).to receive(:retrieve!).and_return true 104 | expect_any_instance_of(OneviewSDK::ServerHardware).to receive(:power_off).and_return true 105 | expect(profile).to receive(:update) 106 | expect(profile).to receive(:refresh).and_return true 107 | ret_val = @driver_120.instance_eval { enable_boot_from_san(a, m, profile) } 108 | target = ret_val['connections'].last['boot']['targets'].first 109 | expect(target['arrayWwpn']).to eq(ret_val['sanStorage']['volumeAttachments'].first['storagePaths'].last['storageTargets'].first.delete(':')) 110 | expect(target['lun']).to eq(ret_val['sanStorage']['volumeAttachments'].first['lun']) 111 | end 112 | 113 | it "doesn't update the profile if it doesn't need to" do 114 | a = action_handler 115 | m = machine_spec.name 116 | profile = OneviewSDK::ServerProfile.from_file(@ov_120, profile_120) 117 | expect(profile).to_not receive(:update) 118 | @driver_120.instance_eval { enable_boot_from_san(a, m, profile) } 119 | end 120 | 121 | it 'raises an error if a connection ID is invalid' do 122 | a = action_handler 123 | m = machine_spec.name 124 | profile = OneviewSDK::ServerProfile.from_file(@ov_120, profile_120) 125 | profile['sanStorage']['volumeAttachments'].first['storagePaths'].last['connectionId'] = 99 126 | expect { @driver_120.instance_eval { enable_boot_from_san(a, m, profile) } }.to raise_error(/Connection 99 not found/) 127 | end 128 | 129 | it 'raises an error if a connection is marked for boot but not bootable' do 130 | a = action_handler 131 | m = machine_spec.name 132 | profile = OneviewSDK::ServerProfile.from_file(@ov_120, profile_120) 133 | profile['connections'].last['boot']['priority'] = 'NotBootable' 134 | expect { @driver_120.instance_eval { enable_boot_from_san(a, m, profile) } }.to raise_error(/connection is not marked as bootable/) 135 | end 136 | end 137 | 138 | end 139 | -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v120/server_profile_web01_with_san.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "type": "ServerProfileV4", 4 | "uri": "/rest/server-profiles/1c5e807d-acbe-4ee8-868b-2fb0b6504476", 5 | "name": "web01", 6 | "description": "Web server machine", 7 | "serialNumber": "VCGE9KB042", 8 | "uuid": "1c5e807d-acbe-4ee8-868b-2fb0b6504476", 9 | "serverHardwareUri": "/rest/server-hardware/31363636-3136-584D-5132-333230314D38", 10 | "serverHardwareTypeUri": "/rest/server-hardware-types/2947DC35-BE48-4075-A3FD-254A9B42F5BD", 11 | "enclosureGroupUri": "/rest/enclosure-groups/3a11ccdd-b352-4046-a568-a8b0faa6cc39", 12 | "enclosureUri": "/rest/enclosures/09SGH236PMVW", 13 | "enclosureBay": 2, 14 | "affinity": "Bay", 15 | "associatedServer": null, 16 | "hideUnusedFlexNics": true, 17 | "firmware": { 18 | "forceInstallFirmware": false, 19 | "manageFirmware": true, 20 | "firmwareBaselineUri": "/rest/firmware-drivers/bp-hp-service-pack-for-proliant-oneview-2014-11-30-05" 21 | }, 22 | "macType": "Virtual", 23 | "wwnType": "Virtual", 24 | "serialNumberType": "Virtual", 25 | "category": "server-profiles", 26 | "created": "20150810T040139.738Z", 27 | "modified": "20150810T042450.221Z", 28 | "status": "OK", 29 | "state": "Normal", 30 | "inProgress": false, 31 | "taskUri": "/rest/tasks/2A17C3F9-6DBF-40B1-B99E-E8BA40848B40", 32 | "connections": [ 33 | { 34 | "id": 1, 35 | "name": "Altair PXE 1133", 36 | "functionType": "Ethernet", 37 | "deploymentStatus": "Deployed", 38 | "networkUri": "/rest/ethernet-networks/02b0b5c3-1a0a-4d5f-b5c9-0c7532cb1e5e", 39 | "portId": "Flb 1:1-a", 40 | "interconnectUri": "/rest/interconnects/34501559-719f-4393-9fb1-a43714037f06", 41 | "macType": "Virtual", 42 | "wwpnType": "Virtual", 43 | "mac": "11:11:11:11:01:14", 44 | "wwnn": null, 45 | "wwpn": null, 46 | "requestedMbps": "2500", 47 | "allocatedMbps": 2500, 48 | "maximumMbps": 10000, 49 | "boot": { 50 | "priority": "Primary" 51 | } 52 | }, 53 | { 54 | "id": 2, 55 | "name": "corpnet 10", 56 | "functionType": "Ethernet", 57 | "deploymentStatus": "Deployed", 58 | "networkUri": "/rest/ethernet-networks/7a4698ae-5933-4e2e-8af3-57893c23a2d2", 59 | "portId": "Flb 1:2-a", 60 | "interconnectUri": "/rest/interconnects/d6c76eb3-10e6-43bf-95a6-ec824dc7bb2e", 61 | "macType": "Virtual", 62 | "wwpnType": "Virtual", 63 | "mac": "11:11:11:11:01:15", 64 | "wwnn": null, 65 | "wwpn": null, 66 | "requestedMbps": "2500", 67 | "allocatedMbps": 2500, 68 | "maximumMbps": 10000, 69 | "boot": { 70 | "priority": "NotBootable" 71 | } 72 | }, 73 | { 74 | "id": 3, 75 | "name": "san1", 76 | "functionType": "FibreChannel", 77 | "deploymentStatus": "Deployed", 78 | "networkUri": "/rest/fc-networks/2c04a682-66b4-4a64-8c2d-3095937a8e7e", 79 | "portId": "Flb 1:1-b", 80 | "interconnectUri": "/rest/interconnects/f43ee5ba-a3b5-44c3-a299-4cc9c100debc", 81 | "macType": "Virtual", 82 | "wwpnType": "Virtual", 83 | "mac": "6E:D2:84:B0:08:9D", 84 | "wwnn": "10:00:fa:a9:af:e0:04:4d", 85 | "wwpn": "10:00:fa:a9:af:e0:04:4c", 86 | "requestedMbps": "4000", 87 | "allocatedMbps": 4000, 88 | "maximumMbps": 4000, 89 | "boot": { 90 | "priority": "Primary", 91 | "targets": [ 92 | { 93 | "arrayWwpn": "20540002AC00159E", 94 | "lun": "0" 95 | } 96 | ] 97 | } 98 | }, 99 | { 100 | "id": 4, 101 | "name": "san2", 102 | "functionType": "FibreChannel", 103 | "deploymentStatus": "Deployed", 104 | "networkUri": "/rest/fc-networks/93c97ad9-3e6d-4cc4-8b37-3ef3a6a9cf77", 105 | "portId": "Flb 1:2-b", 106 | "interconnectUri": "/rest/interconnects/964c1236-4eca-4410-b219-911e6ae0b731", 107 | "macType": "Virtual", 108 | "wwpnType": "Virtual", 109 | "mac": "6E:D2:84:B0:08:9E", 110 | "wwnn": "10:00:fa:a9:af:e0:04:4f", 111 | "wwpn": "10:00:fa:a9:af:e0:04:4e", 112 | "requestedMbps": "4000", 113 | "allocatedMbps": 4000, 114 | "maximumMbps": 4000, 115 | "boot": { 116 | "priority": "Secondary", 117 | "targets": [ 118 | { 119 | "arrayWwpn": "21210002AC00159E", 120 | "lun": "0" 121 | } 122 | ] 123 | } 124 | } 125 | ], 126 | "bootMode": null, 127 | "boot": { 128 | "manageBoot": true, 129 | "order": [ 130 | "HardDisk", 131 | "PXE", 132 | "CD", 133 | "Floppy", 134 | "USB" 135 | ] 136 | }, 137 | "bios": { 138 | "manageBios": true, 139 | "overriddenSettings": [ 140 | { 141 | "id": "158", 142 | "value": "2" 143 | }, 144 | { 145 | "id": "181", 146 | "value": "1" 147 | }, 148 | { 149 | "id": "176", 150 | "value": "1" 151 | } 152 | ] 153 | }, 154 | "localStorage": { 155 | "logicalDrives": [], 156 | "manageLocalStorage": false, 157 | "initialize": false 158 | }, 159 | "sanStorage": { 160 | "volumeAttachments": [ 161 | { 162 | "storagePaths": [ 163 | { 164 | "storageTargets": ["20:54:00:02:AC:00:15:9E"], 165 | "storageTargetType": "Auto", 166 | "connectionId": 3, 167 | "isEnabled": true, 168 | "status": "OK" 169 | }, 170 | { 171 | "storageTargets": ["21:21:00:02:AC:00:15:9E"], 172 | "storageTargetType": "Auto", 173 | "connectionId": 4, 174 | "isEnabled": true, 175 | "status": "OK" 176 | } 177 | ], 178 | "state": "Attached", 179 | "volumeStoragePoolUri": "/rest/storage-pools/707E383B-56F6-48A1-BFF1-782BB2AC6BA7", 180 | "volumeStorageSystemUri": "/rest/storage-systems/1405534", 181 | "lun": "0", 182 | "lunType": "Manual", 183 | "volumeUri": "/rest/storage-volumes/1B5D3CA2-6C5B-41C2-8B97-1821F1883F22", 184 | "status": "OK", 185 | "id": 1 186 | } 187 | ], 188 | "hostOSType": "RHE Linux (5.x, 6.x)", 189 | "manageSanStorage": true 190 | }, 191 | "eTag": "1439179303124/6" 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v120/server-profiles_name_Template-WebServerWithSAN.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "ServerProfileListV4", 3 | "members": [ 4 | { 5 | "type": "ServerProfileV4", 6 | "uri": "/rest/server-profiles/a16654c6-d12d-4e42-aa04-8868cf3dc31b", 7 | "name": "Template - Web Server with SAN", 8 | "description": "Web server machine template with SAN", 9 | "serialNumber": "VCGE9KB035", 10 | "uuid": "a16654c6-d12d-4e42-aa04-8868cf3dc31a", 11 | "serverHardwareUri": null, 12 | "serverHardwareTypeUri": "/rest/server-hardware-types/2947DC35-BE48-4075-A3FD-254A9B42F5BD", 13 | "enclosureGroupUri": "/rest/enclosure-groups/3a11ccdd-b352-4046-a568-a8b0faa6cc39", 14 | "enclosureUri": null, 15 | "enclosureBay": null, 16 | "affinity": "Bay", 17 | "associatedServer": null, 18 | "hideUnusedFlexNics": true, 19 | "firmware": { 20 | "forceInstallFirmware": false, 21 | "manageFirmware": true, 22 | "firmwareBaselineUri": "/rest/firmware-drivers/bp-hp-service-pack-for-proliant-oneview-2014-11-30-05" 23 | }, 24 | "macType": "Virtual", 25 | "wwnType": "Virtual", 26 | "serialNumberType": "Virtual", 27 | "category": "server-profiles", 28 | "created": "20150730T115836.727Z", 29 | "modified": "20150807T051446.275Z", 30 | "status": "OK", 31 | "state": "Normal", 32 | "inProgress": false, 33 | "taskUri": "/rest/tasks/26235118-827A-445D-9E5D-F2BBCAC8E9F1", 34 | "connections": [ 35 | { 36 | "id": 1, 37 | "name": "Altair PXE 1133", 38 | "functionType": "Ethernet", 39 | "deploymentStatus": "Reserved", 40 | "networkUri": "/rest/ethernet-networks/02b0b5c3-1a0a-4d5f-b5c9-0c7532cb1e5e", 41 | "portId": "Flb 1:1-a", 42 | "interconnectUri": null, 43 | "macType": "Virtual", 44 | "wwpnType": "Virtual", 45 | "mac": "11:11:11:11:00:D8", 46 | "wwnn": null, 47 | "wwpn": null, 48 | "requestedMbps": "2500", 49 | "allocatedMbps": 2500, 50 | "maximumMbps": 10000, 51 | "boot": { 52 | "priority": "Primary" 53 | } 54 | }, 55 | { 56 | "id": 2, 57 | "name": "corpnet 10", 58 | "functionType": "Ethernet", 59 | "deploymentStatus": "Reserved", 60 | "networkUri": "/rest/ethernet-networks/7a4698ae-5933-4e2e-8af3-57893c23a2d2", 61 | "portId": "Flb 1:2-a", 62 | "interconnectUri": null, 63 | "macType": "Virtual", 64 | "wwpnType": "Virtual", 65 | "mac": "11:11:11:11:00:D9", 66 | "wwnn": null, 67 | "wwpn": null, 68 | "requestedMbps": "2500", 69 | "allocatedMbps": 2500, 70 | "maximumMbps": 10000, 71 | "boot": { 72 | "priority": "NotBootable" 73 | } 74 | }, 75 | { 76 | "id": 3, 77 | "name": "san1", 78 | "functionType": "FibreChannel", 79 | "deploymentStatus": "Deployed", 80 | "networkUri": "/rest/fc-networks/2c04a682-66b4-4a64-8c2d-3095937a8e7e", 81 | "portId": "Flb 1:1-b", 82 | "interconnectUri": "/rest/interconnects/f43ee5ba-a3b5-44c3-a299-4cc9c100debc", 83 | "macType": "Virtual", 84 | "wwpnType": "Virtual", 85 | "mac": "11:11:11:11:00:E1", 86 | "wwnn": "10:00:fa:a9:af:e0:04:5d", 87 | "wwpn": "10:00:fa:a9:af:e0:04:5c", 88 | "requestedMbps": "4000", 89 | "allocatedMbps": 4000, 90 | "maximumMbps": 4000, 91 | "boot": { 92 | "priority": "Primary", 93 | "targets": [{ "arrayWwpn": "20540002AC00159E", "lun": "0" }] 94 | } 95 | }, 96 | { 97 | "id": 4, 98 | "name": "san2", 99 | "functionType": "FibreChannel", 100 | "deploymentStatus": "Deployed", 101 | "networkUri": "/rest/fc-networks/93c97ad9-3e6d-4cc4-8b37-3ef3a6a9cf77", 102 | "portId": "Flb 1:2-b", 103 | "interconnectUri": "/rest/interconnects/964c1236-4eca-4410-b219-911e6ae0b731", 104 | "macType": "Virtual", 105 | "wwpnType": "Virtual", 106 | "mac": "11:11:11:11:00:E2", 107 | "wwnn": "10:00:fa:a9:af:e0:04:5f", 108 | "wwpn": "10:00:fa:a9:af:e0:04:5e", 109 | "requestedMbps": "4000", 110 | "allocatedMbps": 4000, 111 | "maximumMbps": 4000, 112 | "boot": { 113 | "priority": "Secondary", 114 | "targets": [{ "arrayWwpn": "21210002AC00159F", "lun": "0" }] 115 | } 116 | } 117 | ], 118 | "bootMode": null, 119 | "boot": { 120 | "manageBoot": true, 121 | "order": [ 122 | "HardDisk", 123 | "PXE", 124 | "CD", 125 | "Floppy", 126 | "USB" 127 | ] 128 | }, 129 | "bios": { 130 | "manageBios": true, 131 | "overriddenSettings": [ 132 | { 133 | "id": "176", 134 | "value": "1" 135 | }, 136 | { 137 | "id": "181", 138 | "value": "1" 139 | }, 140 | { 141 | "id": "158", 142 | "value": "2" 143 | } 144 | ] 145 | }, 146 | "localStorage": { 147 | "manageLocalStorage": false, 148 | "initialize": false, 149 | "logicalDrives": null 150 | }, 151 | "sanStorage": { 152 | "volumeAttachments": [ 153 | { 154 | "storagePaths": [ 155 | { 156 | "storageTargets": [ 157 | "21:21:00:02:AC:00:15:9E" 158 | ], 159 | "storageTargetType": "Auto", 160 | "connectionId": 4, 161 | "isEnabled": true, 162 | "status": "OK" 163 | }, 164 | { 165 | "storageTargets": [ 166 | "20:54:00:02:AC:00:15:9E" 167 | ], 168 | "storageTargetType": "Auto", 169 | "connectionId": 3, 170 | "isEnabled": true, 171 | "status": "OK" 172 | } 173 | ], 174 | "state": "Attached", 175 | "volumeStoragePoolUri": "/rest/storage-pools/707E383B-56F6-48A1-BFF1-782BB2AC6BA7", 176 | "volumeStorageSystemUri": "/rest/storage-systems/1405534", 177 | "lun": "0", 178 | "lunType": "Manual", 179 | "volumeUri": "/rest/storage-volumes/1B5D3CA2-6C5B-41C2-8B97-1821F1883F22", 180 | "status": "OK", 181 | "id": 1 182 | } 183 | ], 184 | "hostOSType": "RHE Linux (5.x, 6.x)", 185 | "manageSanStorage": true 186 | }, 187 | "eTag": "1438924486161/12" 188 | } 189 | ], 190 | "total": 1, 191 | "start": 0, 192 | "prevPageUri": null, 193 | "nextPageUri": null, 194 | "count": 1, 195 | "category": "server-profiles", 196 | "created": "20150810T223058.112Z", 197 | "eTag": "20150810T223058.112Z", 198 | "modified": "20150810T223058.112Z", 199 | "uri": "/rest/server-profiles?filter=name%20matches%20'Template%20-%20Web%20Server%20with%20SAN'&sort=name:asc" 200 | } 201 | -------------------------------------------------------------------------------- /examples/ICsp/chef-settings-linux: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ### This script is for custom setting for RHEL deployments 4 | ### using Insight Control server provisioning 5 | 6 | 7 | # This script injects various required server settings 8 | # needed by Chef (setting proxy to connect to Internet, 9 | # Yum repository configurations, SSL certification setting, 10 | # and whether login should be enabled using username/password) 11 | # into a RHEL deployment. 12 | 13 | # To use this script, add it to your RHEL Build Plan 14 | # just after the Integrate Linux HP SA Agent step and 15 | # before the Reboot step. 16 | 17 | 18 | # The location of the server filesystem before the final reboot 19 | MNTPREFIX=/mnt/sysimage 20 | 21 | ### Shell variables that provide the server settings needed by chef. 22 | ### Users have to edit the value of these variables as per the requirements. 23 | ### Users who need to set these variables can do so by editing these variables below. 24 | ### Variable CHEF_PROXYSERVER is used to provide the proxy server address. 25 | ### Variable YUM_REPOSITORY_INFO is used to provide the yum repository information 26 | ### Variable CHEF_CERT is used to provide the SSH certificate information to be copied into the authoriation files. 27 | ### Variable LOGIN_DISABLED should be set to YES/yes if the user requires to diasable user login and should be set ### to NO/no if LOGIN using username/password should not be disabled 28 | 29 | CHEF_PROXYSERVER="" 30 | YUM_REPOSITORY_INFO="" 31 | CHEF_CERT="" 32 | LOGIN_DISABLED="" 33 | 34 | ### Inject required proxy information for internet access 35 | ### if needed. To use this setting, edit the script and set the CHEF_PROXYSERVER variable 36 | ### with the desired 37 | ### proxy server. That same proxy server will be used for 38 | ### HTTP, HTTPS, and FTP. 39 | 40 | echo 41 | 42 | PROXYSERVER=$CHEF_PROXYSERVER 43 | if [ -n "$PROXYSERVER" ] 44 | then 45 | # Proxy server defined - write the info 46 | OUTFILE=/etc/profile.d/proxy.sh 47 | echo "Writing proxy configuration information..." 48 | echo "Proxy set to: $PROXYSERVER" 49 | cat < $MNTPREFIX$OUTFILE 50 | PROXY="$PROXYSERVER" 51 | export http_proxy=\$PROXY 52 | export HTTP_PROXY=\$PROXY 53 | export https_proxy=\$PROXY 54 | export HTTPS_PROXY=\$PROXY 55 | export ftp_proxy=\$PROXY 56 | export FTP_PROXY=\$PROXY 57 | export no_proxy="localhost,127.0.0.1" 58 | export NO_PROXY="localhost,127.0.0.1" 59 | PROXYINFO 60 | 61 | ### Update sudoers file 62 | 63 | OUTFILE=/etc/sudoers 64 | echo 65 | echo "Updating sudoers file..." 66 | echo 'Defaults env_keep += "http_proxy https_proxy no_proxy"' >> $MNTPREFIX$OUTFILE 67 | echo "Done." 68 | else 69 | # No proxy server defined. Non fatal informational message. 70 | echo "INFO - No proxy server was defined. To set a proxy server" 71 | echo "edit the script and set the CHEF_PROXYSERVER shell variable" 72 | echo "to the full URL of your proxy server." 73 | fi 74 | 75 | 76 | 77 | 78 | 79 | 80 | ### Inject the yum repository information 81 | ### To use this setting you must edit the script and set the variable YUM_REPOSITORY_INFO 82 | ### This variable should contian the entire yum repository 83 | ### definition, so at a minimum it should look like this: 84 | ### 85 | ### [Your-repository-name] 86 | ### name=Your-repository-name 87 | ### baseurl=http://your.repository.url 88 | ### 89 | ### It should contian any other options as required by your site. 90 | ### These settings will all go into /etc/yum.repos.d/chef.repo 91 | 92 | echo 93 | # De-reference the YUM_REPOSITORY_INFO shell variable. 94 | YUMINFO=$YUM_REPOSITORY_INFO 95 | if [ -n "$YUMINFO" ] 96 | then 97 | OUTFILE=/etc/yum.repos.d/chef.repo 98 | echo 99 | echo "Writing yum repository info..." 100 | echo "$YUMINFO" > $MNTPREFIX$OUTFILE 101 | if [ -n "$PROXYSERVER" ] 102 | then 103 | # Proxy server defined - write yum proxy info 104 | OUTFILE=/etc/yum.conf 105 | echo "proxy=$PROXYSERVER" >> $MNTPREFIX$OUTFILE 106 | fi 107 | echo "Done." 108 | else 109 | echo "INFO - No yum repository information was defined. To define" 110 | echo "a yum repository for this installation, edit the script and " 111 | echo "set the YUM_REPOSITORY_INFO varaible" 112 | echo " to the full yum repository definition." 113 | echo "At a minimum the definition should look like this:" 114 | echo 115 | echo "[Your-repository-name]" 116 | echo "name=Your-repository-name" 117 | echo "baseurl=http://your.repository.url" 118 | echo 119 | echo "Be sure to include any other options that your sire requires." 120 | fi 121 | 122 | 123 | 124 | 125 | 126 | ### Inject the SSH certificate for access 127 | 128 | # The script gets the public SSH keys from the CHEF_CERT variable . 129 | # Chef users should assign this variable by editing the script and setting the appropriate CHEF_CERT. 130 | # CHEF_CERT variable should contain the desired public SSH keys to put into the root 131 | # authorized_keys file. If no key is found, it reports it but it's 132 | # not considered an error. 133 | 134 | echo 135 | 136 | PUBLICKEY=$CHEF_CERT 137 | if [ -n "$PUBLICKEY" ] 138 | then 139 | # Add the key to the /root/.ssh/authorized_keys file 140 | # and make sure the owner and permissions are OK 141 | SSHDIR=$MNTPREFIX/root/.ssh 142 | echo "Adding the SSH key for this server" 143 | echo "to /root/.ssh/authorized_keys file" 144 | # If the .ssh directory isn't there, create it. 145 | if [ ! -e $SSHDIR ] 146 | then 147 | mkdir $SSHDIR 148 | chmod 700 $SSHDIR 149 | fi 150 | echo "$PUBLICKEY" >> $SSHDIR/authorized_keys 151 | chown root $SSHDIR/authorized_keys 152 | chmod 600 $SSHDIR/authorized_keys 153 | echo "Done" 154 | else 155 | # No SSH key was set by the user. 156 | echo "INFO - The CHEF_CERT for this server" 157 | echo "was empty. Edit this script and set the CHEF_CERT variable to set SSH Key." 158 | echo "No SSH keys will be added to this server." 159 | fi 160 | 161 | 162 | ### check if the user requires the login to be disabled. If yes do the necessary changes in the ssh config file. 163 | 164 | # If the user has set the LOGIN_DISABLED to "yes" then the user has to set a valid SSH key. 165 | echo 166 | echo "Checking the LOGIN_DISABLED setting." 167 | 168 | if [ "$LOGIN_DISABLED" = "YES" ] || [ "$LOGIN_DISABLED" = "yes" ] 169 | then 170 | if [ -z "$PUBLICKEY" ] 171 | then 172 | echo 173 | echo "ERROR: You cannot set LOGIN_DISABLED variable to YES" 174 | echo "without setting valid SSH key." 175 | echo "Please set the CHEF_CERT variable to a valid SSH key and try again." 176 | echo "Password Logins will not be disabled." 177 | else 178 | if [ -n "$PUBLICKEY" ] 179 | then 180 | SSH_CONFIGFILE="/etc/ssh/sshd_config" 181 | BACKUP="_backup" 182 | cp $MNTPREFIX$SSH_CONFIGFILE $MNTPREFIX$SSH_CONFIGFILE$BACKUP 183 | cat $MNTPREFIX$SSH_CONFIGFILE$BACKUP | sed '/^PasswordAuthentication/d' > $MNTPREFIX$SSH_CONFIGFILE 184 | echo "PasswordAuthentication no" >> $MNTPREFIX$SSH_CONFIGFILE 185 | echo "RSAAuthentication yes" >> $MNTPREFIX$SSH_CONFIGFILE 186 | echo "PubkeyAuthentication yes" >> $MNTPREFIX$SSH_CONFIGFILE 187 | echo 188 | echo "Disabling username and password for login. You must use SSH Keys for login." 189 | fi 190 | fi 191 | else 192 | if [ "$LOGIN_DISABLED" = "NO" ] ||[ "$LOGIN_DISABLED" = "no" ] 193 | then 194 | echo 195 | echo "INFO: Nothing to be done for Login setting." 196 | fi 197 | fi 198 | -------------------------------------------------------------------------------- /spec/support/fixtures/oneview/v120/server-profiles_sn_VCGE9KB042.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "ServerProfileListV4", 3 | "members": [ 4 | { 5 | "type": "ServerProfileV4", 6 | "uri": "/rest/server-profiles/1c5e807d-acbe-4ee8-868b-2fb0b6504476", 7 | "name": "chef-web01", 8 | "description": "Web server machine template", 9 | "serialNumber": "VCGE9KB042", 10 | "uuid": "1c5e807d-acbe-4ee8-868b-2fb0b6504476", 11 | "serverHardwareUri": "/rest/server-hardware/31363636-3136-584D-5132-333230314D38", 12 | "serverHardwareTypeUri": "/rest/server-hardware-types/2947DC35-BE48-4075-A3FD-254A9B42F5BD", 13 | "enclosureGroupUri": "/rest/enclosure-groups/3a11ccdd-b352-4046-a568-a8b0faa6cc39", 14 | "enclosureUri": "/rest/enclosures/09SGH236PMVW", 15 | "enclosureBay": 2, 16 | "affinity": "Bay", 17 | "associatedServer": null, 18 | "hideUnusedFlexNics": true, 19 | "firmware": { 20 | "forceInstallFirmware": false, 21 | "manageFirmware": true, 22 | "firmwareBaselineUri": "/rest/firmware-drivers/bp-hp-service-pack-for-proliant-oneview-2014-11-30-05" 23 | }, 24 | "macType": "Virtual", 25 | "wwnType": "Virtual", 26 | "serialNumberType": "Virtual", 27 | "category": "server-profiles", 28 | "created": "20150810T040139.738Z", 29 | "modified": "20150810T042450.221Z", 30 | "status": "OK", 31 | "state": "Normal", 32 | "inProgress": false, 33 | "taskUri": "/rest/tasks/2A17C3F9-6DBF-40B1-B99E-E8BA40848B40", 34 | "connections": [ 35 | { 36 | "id": 1, 37 | "name": "Altair PXE 1133", 38 | "functionType": "Ethernet", 39 | "deploymentStatus": "Deployed", 40 | "networkUri": "/rest/ethernet-networks/02b0b5c3-1a0a-4d5f-b5c9-0c7532cb1e5e", 41 | "portId": "Flb 1:1-a", 42 | "interconnectUri": "/rest/interconnects/34501559-719f-4393-9fb1-a43714037f06", 43 | "macType": "Virtual", 44 | "wwpnType": "Virtual", 45 | "mac": "11:11:11:11:01:14", 46 | "wwnn": null, 47 | "wwpn": null, 48 | "requestedMbps": "2500", 49 | "allocatedMbps": 2500, 50 | "maximumMbps": 10000, 51 | "boot": { 52 | "priority": "Primary" 53 | } 54 | }, 55 | { 56 | "id": 2, 57 | "name": "corpnet 10", 58 | "functionType": "Ethernet", 59 | "deploymentStatus": "Deployed", 60 | "networkUri": "/rest/ethernet-networks/7a4698ae-5933-4e2e-8af3-57893c23a2d2", 61 | "portId": "Flb 1:2-a", 62 | "interconnectUri": "/rest/interconnects/d6c76eb3-10e6-43bf-95a6-ec824dc7bb2e", 63 | "macType": "Virtual", 64 | "wwpnType": "Virtual", 65 | "mac": "11:11:11:11:01:15", 66 | "wwnn": null, 67 | "wwpn": null, 68 | "requestedMbps": "2500", 69 | "allocatedMbps": 2500, 70 | "maximumMbps": 10000, 71 | "boot": { 72 | "priority": "NotBootable" 73 | } 74 | }, 75 | { 76 | "id": 3, 77 | "name": "san1", 78 | "functionType": "FibreChannel", 79 | "deploymentStatus": "Deployed", 80 | "networkUri": "/rest/fc-networks/2c04a682-66b4-4a64-8c2d-3095937a8e7e", 81 | "portId": "Flb 1:1-b", 82 | "interconnectUri": "/rest/interconnects/f43ee5ba-a3b5-44c3-a299-4cc9c100debc", 83 | "macType": "Virtual", 84 | "wwpnType": "Virtual", 85 | "mac": "6E:D2:84:B0:08:9D", 86 | "wwnn": "10:00:fa:a9:af:e0:04:4d", 87 | "wwpn": "10:00:fa:a9:af:e0:04:4c", 88 | "requestedMbps": "4000", 89 | "allocatedMbps": 4000, 90 | "maximumMbps": 4000, 91 | "boot": { 92 | "priority": "Primary", 93 | "targets": [ 94 | { 95 | "arrayWwpn": "20540002AC00159E", 96 | "lun": "0" 97 | } 98 | ] 99 | } 100 | }, 101 | { 102 | "id": 4, 103 | "name": "san2", 104 | "functionType": "FibreChannel", 105 | "deploymentStatus": "Deployed", 106 | "networkUri": "/rest/fc-networks/93c97ad9-3e6d-4cc4-8b37-3ef3a6a9cf77", 107 | "portId": "Flb 1:2-b", 108 | "interconnectUri": "/rest/interconnects/964c1236-4eca-4410-b219-911e6ae0b731", 109 | "macType": "Virtual", 110 | "wwpnType": "Virtual", 111 | "mac": "6E:D2:84:B0:08:9E", 112 | "wwnn": "10:00:fa:a9:af:e0:04:4f", 113 | "wwpn": "10:00:fa:a9:af:e0:04:4e", 114 | "requestedMbps": "4000", 115 | "allocatedMbps": 4000, 116 | "maximumMbps": 4000, 117 | "boot": { 118 | "priority": "Secondary", 119 | "targets": [ 120 | { 121 | "arrayWwpn": "21210002AC00159E", 122 | "lun": "0" 123 | } 124 | ] 125 | } 126 | } 127 | ], 128 | "bootMode": null, 129 | "boot": { 130 | "manageBoot": true, 131 | "order": [ 132 | "HardDisk", 133 | "PXE", 134 | "CD", 135 | "Floppy", 136 | "USB" 137 | ] 138 | }, 139 | "bios": { 140 | "manageBios": true, 141 | "overriddenSettings": [ 142 | { 143 | "id": "158", 144 | "value": "2" 145 | }, 146 | { 147 | "id": "181", 148 | "value": "1" 149 | }, 150 | { 151 | "id": "176", 152 | "value": "1" 153 | } 154 | ] 155 | }, 156 | "localStorage": { 157 | "logicalDrives": [], 158 | "manageLocalStorage": false, 159 | "initialize": false 160 | }, 161 | "sanStorage": { 162 | "volumeAttachments": [ 163 | { 164 | "storagePaths": [ 165 | { 166 | "storageTargets": ["20:54:00:02:AC:00:15:9E"], 167 | "storageTargetType": "Auto", 168 | "connectionId": 3, 169 | "isEnabled": true, 170 | "status": "OK" 171 | }, 172 | { 173 | "storageTargets": ["21:21:00:02:AC:00:15:9E"], 174 | "storageTargetType": "Auto", 175 | "connectionId": 4, 176 | "isEnabled": true, 177 | "status": "OK" 178 | } 179 | ], 180 | "state": "Attached", 181 | "volumeStoragePoolUri": "/rest/storage-pools/707E383B-56F6-48A1-BFF1-782BB2AC6BA7", 182 | "volumeStorageSystemUri": "/rest/storage-systems/1405534", 183 | "lun": "0", 184 | "lunType": "Manual", 185 | "volumeUri": "/rest/storage-volumes/1B5D3CA2-6C5B-41C2-8B97-1821F1883F22", 186 | "status": "OK", 187 | "id": 1 188 | } 189 | ], 190 | "hostOSType": "RHE Linux (5.x, 6.x)", 191 | "manageSanStorage": true 192 | }, 193 | "eTag": "1439179303124/6" 194 | } 195 | ], 196 | "total": 1, 197 | "start": 0, 198 | "prevPageUri": null, 199 | "nextPageUri": null, 200 | "count": 1, 201 | "category": "server-profiles", 202 | "created": "20150810T223058.112Z", 203 | "eTag": "20150810T223058.112Z", 204 | "modified": "20150810T223058.112Z", 205 | "uri": "/rest/server-profiles?filter=serialNumber%20matches%20'VCGE9KB041'&sort=name:asc" 206 | } 207 | -------------------------------------------------------------------------------- /spec/unit/oneview_helper_spec.rb: -------------------------------------------------------------------------------- 1 | require_relative './../spec_helper' 2 | 3 | RSpec.describe OneviewChefProvisioningDriver::OneViewHelper do 4 | include_context 'shared context' 5 | 6 | let(:helper) do 7 | (Class.new { include OneviewChefProvisioningDriver::OneViewHelper }).new 8 | end 9 | 10 | let(:template_name) do 11 | 'Web Server Template' 12 | end 13 | 14 | let(:profile_name) do 15 | 'chef-web01' 16 | end 17 | 18 | let(:profile_data) do 19 | { 20 | name: template_name, 21 | uri: '/rest/fake2', 22 | connections: [ 23 | { 24 | 'id' => 1, 25 | 'name' => 'net1', 26 | 'functionType' => 'Ethernet', 27 | 'deploymentStatus' => 'Deployed', 28 | 'networkUri' => '/rest/ethernet-networks/fake', 29 | 'portId' => 'Flb 1:1-a', 30 | 'requestedVFs' => 'Auto', 31 | 'allocatedVFs' => nil, 32 | 'interconnectUri' => '/rest/interconnects/fake', 33 | 'macType' => 'Virtual', 34 | 'wwpnType' => 'Virtual', 35 | 'mac' => 'CA:1D:00:00:00:00', 36 | 'wwnn' => nil, 37 | 'wwpn' => nil, 38 | 'requestedMbps' => '2500', 39 | 'allocatedMbps' => 2500, 40 | 'maximumMbps' => 10_000, 41 | 'boot' => { 42 | 'priority' => 'Primary', 43 | 'targets' => [{ 'arrayWwpn' => '20000002AC0008DA', 'lun' => '0' }] 44 | } 45 | } 46 | ], 47 | serialNumber: 'fakesn', 48 | uuid: 'fakeuuid', 49 | taskUri: '/rest/fake3', 50 | enclosureBay: 4, 51 | enclosureUri: '/rest/fake4' 52 | } 53 | end 54 | 55 | describe '#profile_from_template' do 56 | it 'requires a template_name' do 57 | expect { helper.profile_from_template(nil, profile_name) }.to raise_error(/Template name missing/) 58 | end 59 | 60 | before :each do 61 | @profile = OneviewSDK::ServerProfile.new(@ov_200, profile_data) 62 | end 63 | 64 | context 'OneView 2.0' do 65 | before :each do 66 | @template = OneviewSDK::ServerProfileTemplate.new(@ov_200, name: template_name, uri: '/rest/fake') 67 | @new_profile = OneviewSDK::ServerProfile.new(@ov_200, name: profile_name, serverProfileTemplateUri: '/rest/fake') 68 | end 69 | 70 | it 'looks for a ServerProfileTemplate first' do 71 | t = template_name 72 | p = profile_name 73 | expect(OneviewSDK::ServerProfileTemplate).to receive(:find_by).with(@ov_200, name: t).and_return([@template]) 74 | expect(@template).to receive(:new_profile).with(p).and_return(@new_profile) 75 | p = @driver_200.instance_eval { profile_from_template(t, p) } 76 | expect(p['name']).to eq(profile_name) 77 | expect(p['uri']).to be_nil 78 | expect(p['serverProfileTemplateUri']).to eq(@template['uri']) 79 | end 80 | 81 | it 'also looks for a ServerProfile' do 82 | t = template_name 83 | p = profile_name 84 | expect(OneviewSDK::ServerProfileTemplate).to receive(:find_by).and_return [] 85 | expect(OneviewSDK::ServerProfile).to receive(:find_by).with(@ov_200, name: t).and_return([@profile]) 86 | p = @driver_200.instance_eval { profile_from_template(t, p) } 87 | expect(p['name']).to eq(profile_name) 88 | end 89 | 90 | it 'clears out certain attributes from server profiles' do 91 | t = template_name 92 | p = profile_name 93 | expect(OneviewSDK::ServerProfileTemplate).to receive(:find_by).and_return [] 94 | expect(OneviewSDK::ServerProfile).to receive(:find_by).with(@ov_200, name: t).and_return([@profile]) 95 | p = @driver_200.instance_eval { profile_from_template(t, p) } 96 | %w(uri serialNumber uuid taskUri enclosureBay enclosureUri).each do |key| 97 | expect(p[key]).to be_nil 98 | end 99 | %w(wwnn wwpn mac deploymentStatus interconnectUri wwpnType macType).each do |key| 100 | expect(p['connections'].first[key]).to be_nil 101 | end 102 | end 103 | end 104 | 105 | context 'OneView 1.2' do 106 | it 'does not check for a ServerProfileTemplate' do 107 | t = template_name 108 | p = profile_name 109 | expect(OneviewSDK::ServerProfileTemplate).to_not receive(:find_by) 110 | expect(OneviewSDK::ServerProfile).to receive(:find_by).with(@ov_120, name: t).and_return([@profile]) 111 | p = @driver_120.instance_eval { profile_from_template(t, p) } 112 | expect(p['name']).to eq(profile_name) 113 | end 114 | end 115 | end 116 | 117 | describe '#available_hardware_for_profile' do 118 | before :each do 119 | @profile = OneviewSDK::ServerProfile.new(@ov_200, serverHardwareTypeUri: '/rest/fake', enclosureGroupUri: '/rest/fake2') 120 | @hw = OneviewSDK::ServerHardware.new(@ov_200, name: 'Enclosure-1, bay 1', uri: '/rest/fake3') 121 | @hw2 = OneviewSDK::ServerHardware.new(@ov_200, name: 'Enclosure-1, bay 2', uri: '/rest/fake4') 122 | end 123 | 124 | it 'requires the serverHardwareTypeUri to be set' do 125 | p = OneviewSDK::ServerProfile.new(@ov_200, enclosureGroupUri: '/rest/fake2') 126 | expect { helper.available_hardware_for_profile(p) }.to raise_error(OneviewSDK::IncompleteResource, /Must set/) 127 | end 128 | 129 | it 'requires the enclosureGroupUri to be set' do 130 | p = OneviewSDK::ServerProfile.new(@ov_200, serverHardwareTypeUri: '/rest/fake') 131 | expect { helper.available_hardware_for_profile(p) }.to raise_error(OneviewSDK::IncompleteResource, /Must set/) 132 | end 133 | 134 | it 'raises an error if there is no available (matching) hardware' do 135 | expect(@profile).to receive(:get_available_hardware).and_return [] 136 | expect { helper.available_hardware_for_profile(@profile) }.to raise_error(/No available blades/) 137 | end 138 | 139 | it 'returns the first available (matching) hardware if no location is specified' do 140 | expect(@profile).to receive(:get_available_hardware).and_return [@hw, @hw2] 141 | hw = helper.available_hardware_for_profile(@profile) 142 | expect(hw).to eq(@hw) 143 | end 144 | 145 | it 'returns the matching hardware if a location is specified' do 146 | expect(@profile).to receive(:get_available_hardware).and_return [@hw, @hw2] 147 | hw = helper.available_hardware_for_profile(@profile, 'Enclosure-1, bay 2') 148 | expect(hw).to eq(@hw2) 149 | end 150 | 151 | it 'raises an error if a location is specified but that hardware is not available' do 152 | expect(@profile).to receive(:get_available_hardware).and_return [@hw] 153 | expect { helper.available_hardware_for_profile(@profile, 'Enclosure-1, bay 2') }.to raise_error(/doesn't exist or doesn't match/) 154 | end 155 | end 156 | 157 | describe '#wait_for_profile' do 158 | it 'returns immediately if the profile state is Normal' do 159 | profile = OneviewSDK::ServerProfile.new(@ov_200, state: 'Normal') 160 | res = helper.wait_for_profile(action_handler, machine_spec.name, profile) 161 | expect(res).to be true 162 | end 163 | 164 | it 'waits for the profile task if the profile state is not Normal' do 165 | a = action_handler 166 | n = machine_spec.name 167 | profile = OneviewSDK::ServerProfile.new(@ov_200, taskUri: '/rest/fake') 168 | expect(profile).to receive(:[]).with('name').at_least(:once).and_call_original 169 | expect(profile).to receive(:[]).with('taskUri').and_call_original 170 | expect(profile).to receive(:[]).with('state').and_return('Creating', 'Normal') 171 | expect(@ov_200).to receive(:wait_for).with('/rest/fake').and_return true 172 | expect(profile).to receive(:refresh).and_return true 173 | @driver_200.instance_eval { wait_for_profile(a, n, profile) } 174 | end 175 | end 176 | 177 | end 178 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # chef-provisioning-oneview 2 | 3 | Chef Provisioning driver for HPE OneView 4 | 5 | [![Build Status](https://travis-ci.org/HewlettPackard/chef-provisioning-oneview.svg?branch=master)](https://travis-ci.org/HewlettPackard/chef-provisioning-oneview) 6 | [![Gem Version](https://badge.fury.io/rb/chef-provisioning-oneview.svg)](https://badge.fury.io/rb/chef-provisioning-oneview) 7 | 8 | Questions or comments? Join the Gitter room [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/HewlettPackard/chef-provisioning-oneview?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) 9 | 10 | Verified on (may support other versions too, but no guarantees): 11 | - OneView v1.2.0 - 2.0.0 12 | - ICsp v7.4.0 - 7.5.0 13 | 14 | :warning: This driver does not support provisioning with HPE Synergy Image Streamer. It is recommended to use the [HPE OneView Chef cookbook](https://github.com/HewlettPackard/oneview-chef) to do that. 15 | 16 | # Installation 17 | 18 | - This program is meant to run inside the chef-client. To install it, add the following to a Chef recipe and run it: 19 | 20 | ```ruby 21 | chef_gem 'chef-provisioning-oneview' 22 | ``` 23 | 24 | 25 | # Credentials & Configuration 26 | 27 | There are a few different ways to provide credentials and configuration for this driver. 28 | 29 | - In a recipe using the `with_driver` method: 30 | 31 | ```ruby 32 | # The basic usage is: 33 | # with_driver canonical_url, driver_options 34 | 35 | with_driver 'oneview:https://oneview.example.com', { 36 | oneview: { 37 | url: 'https://oneview2.example.com' # Will be overridden by the canonical url above 38 | user: 'Administrator', 39 | password: 'secret123', 40 | token: 'token123', # Optional. Use EITHER this or the username & password 41 | ssl_enabled: true, # Optional. Defaults to true 42 | timeout: 10 # Optional. In seconds 43 | }, 44 | icsp: { 45 | url: 'https://icsp.example.com' 46 | user: 'Admin', 47 | password: 'secret456', 48 | ssl_enabled: true, # Optional. Defaults to true 49 | timeout: 20 # Optional. In seconds 50 | } 51 | } 52 | ``` 53 | 54 | - You can also use the following options in your `knife.rb` file: 55 | 56 | ```ruby 57 | # (knife.rb) 58 | # (in addition to all the normal stuff like node_name, client_key, validation_client_name, validation_key, chef_server_url, etc.) 59 | knife[:oneview_url] = 'https://oneview.example.com' 60 | knife[:oneview_username] = 'Administrator' 61 | knife[:oneview_password] = 'password123' 62 | knife[:oneview_token] = 'token123' # Use EITHER this or the username & password 63 | knife[:oneview_ignore_ssl] = true # For self-signed certs (discouraged) 64 | knife[:oneview_timeout] = 10 # Optional. In seconds 65 | 66 | knife[:icsp_url] = 'https://icsp.example.com' 67 | knife[:icsp_username] = 'Administrator' 68 | knife[:icsp_password] = 'password123' 69 | knife[:icsp_ignore_ssl] = true # For self-signed certs (discouraged) 70 | knife[:icsp_timeout] = 20 # Optional. In seconds 71 | 72 | knife[:node_root_password] = 'password123' 73 | 74 | # If your Chef server has self-signed certs: 75 | verify_api_cert false 76 | ssl_verify_mode :verify_none 77 | ``` 78 | 79 | - Finally, there are a few environment variables that you can set: 80 | 81 | ```bash 82 | export ONEVIEWSDK_USER='Administrator' 83 | export ONEVIEWSDK_PASSWORD='secret123' 84 | export ONEVIEWSDK_TOKEN='token123' 85 | ``` 86 | 87 | Since there are a few diferent ways of providing the same config values, here's the order of evaluation: 88 | - **OneView URL:** canonical_url (ie `oneview:https://oneview.example.com`), driver_options[:oneview][:url], knife[:oneview_url], ENV['ONEVIEWSDK_URL'] 89 | - **OneView user, password, & token:** driver_options, knife, environment variable 90 | - **ICSP url, user, & password:** driver_options, knife 91 | 92 | Note: ICSP is not required, so if you don't want to use it, you can leave out those config options and it will be ignored. 93 | 94 | ### Additional Setup 95 | 96 | - Your OneView, Insight Controll Server Provisioning(ICSP), and Chef server must be trusted by your certificate stores. See [examples/ssl_issues.md](examples/ssl_issues.md) for more info on how to do this. 97 | - You can also use the OneView SDK cli tool to import your OneView cert. See [this](https://github.com/HewlettPackard/oneview-sdk-ruby#cli). 98 | - Your OneView and ICSP servers must be set up beforehand. Unfortunately, this driver doesn't do that for you too. 99 | 100 | # Usage 101 | 102 | Example recipe: 103 | ```ruby 104 | require 'chef/provisioning' 105 | 106 | with_driver 'oneview:https://oneview.example.com', { 107 | oneview: { user: 'Administrator', password: 'secret123' }, 108 | icsp: { url: 'https://icsp.example.com' user: 'Admin', password: 'secret456' } 109 | } 110 | 111 | machine 'web01' do 112 | recipe 'my_server_cookbook::default' 113 | 114 | machine_options driver_options: { 115 | server_template: 'Web Server Template', # Name of Template OR Server Profile 116 | os_build: 'CHEF-RHEL-6.5-x64', # Name of OS Build Plan on ICSP. Supports array of strings also. 117 | server_location: 'Encl1, bay 16', # Optional. Use to provision a specific server 118 | 119 | host_name: 'chef-web01', 120 | ip_address: 'xx.xx.xx.xx', # For bootstrapping. Deprecated in favor of { bootstrap: true } in connection; see below 121 | domainType: 'workgroup', 122 | domainName: 'sub.domain.com', 123 | mask: '255.255.255.0', # Can set here or in individual connections below 124 | dhcp: false, # Can set here or in individual connections below 125 | gateway: 'xx.xx.xx.1', # Can set here or in individual connections below 126 | dns: 'xx.xx.xx.xx,xx.xx.xx.xx,xx.xx.xx.xx', # Can set here or in individual connections below 127 | connections: { 128 | #1 => { ... } (Reserved for PXE on our setup) 129 | 2 => { 130 | ip4Address: 'xx.xx.xx.xx', 131 | mask: '255.255.254.0', # Optional. Overrides mask property above 132 | dhcp: false # Optional. Overrides dhcp property above 133 | gateway: 'xx.xx.xx.1' # Optional. Overrides gateway property above 134 | dns: 'xx.xx.xx.xx' # Optional. Overrides dns property above 135 | bootstrap: true # Set this on 1 connection only. Tells Chef which connection to use to bootstrap. 136 | }, 137 | 3 => { 138 | dhcp: true # Optional. Overrides dhcp property above 139 | gateway: :none # Optional. Overrides gateway property above 140 | dns: :none # Optional. Overrides dns property above 141 | } 142 | }, 143 | skip_network_configuration: false, # Default. Set to true for EXSi hosts, etc. 144 | custom_attributes: { 145 | chefCert: 'ssh-rsa AA...' # Optional 146 | } 147 | }, 148 | transport_options: { 149 | user: 'root', # Optional. Defaults to 'root' 150 | ssh_options: { 151 | password: Chef::Config.knife[:node_root_password] 152 | } 153 | }, 154 | convergence_options: { 155 | ssl_verify_mode: :verify_none, # Optional. For Chef servers with self-signed certs 156 | bootstrap_proxy: 'http://proxy.example.com:8080' # Optional 157 | } 158 | 159 | chef_environment '_default' 160 | converge true 161 | end 162 | ``` 163 | 164 | See https://github.com/chef/chef-provisioning-ssh for more transport_options. 165 | 166 | NOTE: Some basic connection settings such as :ip4Address and :dhcp are shown in the example recipe, but you can pass in any interface/nic options that exist in the ICsp api for POST requests to /rest/os-deployment-jobs 167 | 168 | ### Custom Attributes 169 | 170 | Insided the custom attributes hash, you can specify any data that you would like to pass into your ICsp build plan scripts or configuration files. For example, to specify a list of trusted public keys to be placed into the node's .ssh/authorized_keys file, add a custom attribute to the machine resource definition: 171 | 172 | ```ruby 173 | custom_attributes: { 174 | chefCert: 'ssh-rsa AA...' 175 | } 176 | ``` 177 | 178 | Then create/modify a custom build script in ICsp that will do something with this data. To access it, use the format: `@variable_name@` or `@variable_name:default_value@`. For our example, we could do something like: 179 | 180 | ```bash 181 | #!/bin/bash 182 | authorized_keys = @chefCert@ 183 | if [ -n "$authorized_keys"]; then 184 | echo -e "$authorized_keys" > /mnt/sysimage/root/.ssh/authorized_keys 185 | fi 186 | ``` 187 | 188 | ### SSH Keys 189 | 190 | To use SSH keys insead of passwords to connect to nodes, you'll need to modify your transport_options to look something like: 191 | 192 | ```ruby 193 | transport_options: { 194 | ssh_options: { 195 | auth_methods: ['publickey'], 196 | keys: ['~/.ssh/id_rsa'] 197 | } 198 | } 199 | ``` 200 | 201 | You'll also need to put the corresponding public key(s) into the node's authorized_keys file during the OS setup. See the Custom Attributes section above for one way to do this. 202 | 203 | ### Behind a proxy 204 | 205 | Add `bootstrap_proxy: 'http://proxy.example.com:8080'` to your convergence_options hash. 206 | Also, make sure your OS build plans set up the proxy configuration in a post OS install script. 207 | 208 | ### SAN Storage 209 | 210 | In order to attach a SAN volume as a bootable volume, the volume name must start with 'boot'; it will be appended with the the profile name on creation. 211 | 212 | ### Switching to a different network after provisioning 213 | 214 | Add `1 => {net: "Deadnetwork", deployNet: "PXE Network", dhcp: true}` to your connections hash. 215 | This will flip the first connection of the newly provisioned machine off of your pxe network to your Deadnetwork right after provisioning. This is helpful for taking the newly provisioned machine off the PXE network as soon as possible. 216 | 217 | ### Adding Nic Teams 218 | 219 | Add `team: 'TeamName'` into a connection in your connections hash. Make sure that you have 2 connections in a team and the name does not include hyphens. This information will be passed to ISCP as the 'teams' custom attribute in the format: `"TeamName1-mac1,mac2|TeamName2-mac6,mac7,mac8"` to be consumed in a custom build plan script. 220 | 221 | # Doing a test run 222 | 223 | This repo contains everything you need to get started, including example recipes and knife configuration files. See the README in the [examples](examples/) directory for how to begin provisioning. 224 | 225 | 226 | # Troubleshooting 227 | 228 | See the [Trouleshooting wiki page](https://github.com/HewlettPackard/chef-provisioning-oneview/wiki/Troubleshooting) 229 | 230 | 231 | # Contributing 232 | 233 | You know the drill. Fork it, branch it, change it, commit it, pull-request it. We're passionate about improving this driver, and glad to accept help to make it better. 234 | 235 | ### Building the Gem 236 | 237 | To build this gem, run `$ rake build` or `gem build chef-provisioning-oneview.gemspec`. 238 | 239 | Then once it's built you can install it by running `$ rake install` or `$ gem install ./chef-provisioning-oneview-.gem`. 240 | 241 | Note: You may need to first install the `ruby-devel` or `ruby-dev` package for your system. 242 | 243 | ### Testing 244 | 245 | - RuboCop: `$ rake rubocop` or `$ rubocop .` 246 | - Rspec: `$ rake spec` or `$ rspec` 247 | - Both: Run `$ rake test` to run both RuboCop and Rspec tests. 248 | 249 | # Authors 250 | 251 | - Jared Smartt - [@jsmartt](https://github.com/jsmartt) 252 | - Matthew Frahry - [@mbfrahry](https://github.com/mbfrahry) 253 | - Andy Claiborne - [@veloandy](https://github.com/veloandy) 254 | - Gunjan Kamle - [@kgunjan](https://github.com/kgunjan) 255 | --------------------------------------------------------------------------------