3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
19 from oslo_log import log as logging
21 from ironic.common.i18n import _
22 from ironic.drivers.modules import ipmitool
23 from ironic.common import exception
24 from ironic.conductor import utils as manager_utils
25 from ironic_virtmedia_driver import virtmedia
27 LOG = logging.getLogger(__name__)
29 REQUIRED_PROPERTIES = {
30 'provisioning_server': 'Provisioning server IP hosting deployment ISO and metadata Floppy images. Required.',
31 'provisioning_server_http_port': 'Provisioning server port where the images can be obtained with http requests. Required.',
32 'vendor': 'Vendor for the installed hardware. Required.',
33 'product_family': 'Product family for the hardware. Required.'
36 COMMON_PROPERTIES = REQUIRED_PROPERTIES.copy()
38 def _parse_driver_info(node):
39 """Gets the information needed for accessing the node.
41 :param node: the Node of interest.
42 :returns: dictionary of information.
43 :raises: InvalidParameterValue if any required parameters are incorrect.
44 :raises: MissingParameterValue if any required parameters are missing.
47 info = node.driver_info or {}
48 missing_info = [key for key in REQUIRED_PROPERTIES if not info.get(key)]
50 raise exception.MissingParameterValue(_(
51 "virtmedia_ipmi driver requires the following parameters to be set in "
52 "node's driver_info: %s.") % missing_info)
54 provisioning_server = info.get('provisioning_server')
55 provisioning_server_http_port = info.get('provisioning_server_http_port')
56 vendor = info.get('vendor')
57 product_family = info.get('product_family')
58 ipmi_params = ipmitool._parse_driver_info(node)
60 'provisioning_server': provisioning_server,
61 'provisioning_server_http_port': provisioning_server_http_port,
63 'product_family': product_family,
65 return dict(ipmi_params.items() + res.items())
67 def _get_hw_library(driver_info):
69 vendor = driver_info.get('vendor').lower()
70 product_family = driver_info.get('product_family').lower()
71 obj = driver_info.get('product_family')
73 modulename = 'ironic_virtmedia_driver.vendors.%s.%s'%(vendor, product_family)
74 if modulename not in sys.modules:
75 modulej = __import__(modulename, fromlist=[''])
76 globals()[modulename] = modulej
78 module = sys.modules[modulename]
81 if obj in dir(module):
82 modj = getattr(module, obj)
85 msg = "Cannot find driver for your hardware from the module Vendor: %s Product family: %s" % (vendor, product_family)
87 raise exception.NotFound(msg)
91 except ImportError as err:
92 msg = "Cannot import driver for your hardware Vendor: %s Product family: %s :: %s"% (vendor, product_family, str(err))
94 raise exception.NotFound(msg)
95 except KeyError as err:
96 LOG.exception("virtmedia has a problem with hw type")
97 raise exception.IronicException("Internal virtmedia error")
100 class VirtualMediaAndIpmiBoot(virtmedia.VirtmediaBoot):
102 """Constructor of VirtualMediaAndIpmiBoot.
104 :raises: InvalidParameterValue, if config option has invalid value.
106 super(VirtualMediaAndIpmiBoot, self).__init__()
108 def _attach_virtual_cd(self, task, image_filename):
109 """Attaches the given url as virtual media on the node.
111 :param node: an ironic node object.
112 :param bootable_iso_filename: a bootable ISO image to attach to.
113 The iso file should be present in NFS/CIFS server.
114 :raises: VirtmediaOperationError if attaching virtual media failed.
117 driver_info = _parse_driver_info(task.node)
119 hw = _get_hw_library(driver_info)
121 while not hw.attach_virtual_cd(image_filename, driver_info, task) and retry_count:
124 LOG.debug("Virtual media attachment failed. Retrying again")
127 LOG.exception("Failed to attach Virtual media. Max retries exceeded")
128 raise exception.InstanceDeployFailure(reason='NFS mount failed!')
130 def _detach_virtual_cd(self, task):
131 """Detaches virtual cdrom on the node.
133 :param node: an ironic node object.
134 :raises: VirtmediaOperationError if eject virtual cdrom failed.
136 driver_info = _parse_driver_info(task.node)
137 hw = _get_hw_library(driver_info)
138 hw.detach_virtual_cd(driver_info, task)
140 def _set_deploy_boot_device(self, task):
141 """Set the boot device for deployment"""
142 driver_info = _parse_driver_info(task.node)
143 hw = _get_hw_library(driver_info)
144 hw.set_boot_device(task)