summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Tantsur <dtantsur@protonmail.com>2021-05-03 17:03:29 +0200
committerDmitry Tantsur <dtantsur@protonmail.com>2021-05-04 14:28:25 +0200
commit929907d68473ae8a433ebb8c4dcb110473d42676 (patch)
tree3b946e32ddbe3e7e91f1a8a88625b2e23af06add
parente79f163837dd2c27f84f693aba0f1575fa2353f7 (diff)
downloadironic-929907d68473ae8a433ebb8c4dcb110473d42676.tar.gz
Bye-bye iSCSI deploy, you served us well
The iSCSI deploy was very easy to start with, but it has since become apparently that it suffers from scalability and maintenance issues. It was deprecated in the Victoria cycle and can now be removed. Hide the guide to upgrade to hardware types since it's very outdated. I had to remove the iBMC diagram since my SVG-fu is not enough to fix it. Change-Id: I2cd6bf7b27fe0be2c08104b0cc37654b506b2e62
-rw-r--r--api-ref/source/samples/driver-get-response.json4
-rw-r--r--api-ref/source/samples/drivers-list-detail-response.json4
-rw-r--r--api-ref/source/samples/nodes-list-details-response.json2
-rw-r--r--bindep.txt1
-rw-r--r--doc/source/admin/drivers.rst2
-rw-r--r--doc/source/admin/drivers/ibmc.rst9
-rw-r--r--doc/source/admin/drivers/idrac.rst2
-rw-r--r--doc/source/admin/drivers/ilo.rst20
-rw-r--r--doc/source/admin/drivers/ipa.rst25
-rw-r--r--doc/source/admin/drivers/irmc.rst2
-rw-r--r--doc/source/admin/interfaces/boot.rst4
-rw-r--r--doc/source/admin/interfaces/deploy.rst25
-rw-r--r--doc/source/admin/node-deployment.rst8
-rw-r--r--doc/source/admin/notifications.rst12
-rw-r--r--doc/source/admin/ramdisk-boot.rst2
-rw-r--r--doc/source/admin/troubleshooting.rst30
-rw-r--r--doc/source/admin/tuning.rst2
-rw-r--r--doc/source/contributor/dev-quickstart.rst13
-rw-r--r--doc/source/contributor/ironic-boot-from-volume.rst1
-rw-r--r--doc/source/contributor/ironic-multitenant-networking.rst1
-rw-r--r--doc/source/images/ironic_standalone_with_ibmc_driver.svg1309
-rw-r--r--doc/source/index.rst1
-rw-r--r--doc/source/install/configure-iscsi.rst5
-rw-r--r--doc/source/install/configure-tenant-networks.rst4
-rw-r--r--doc/source/install/enabling-drivers.rst19
-rw-r--r--doc/source/install/enrollment.rst10
-rw-r--r--doc/source/install/refarch/common.rst17
-rw-r--r--doc/source/install/setup-drivers.rst1
-rw-r--r--doc/source/user/index.rst60
-rw-r--r--etc/ironic/rootwrap.d/ironic-utils.filters3
-rw-r--r--ironic/cmd/dbsync.py2
-rw-r--r--ironic/conf/__init__.py4
-rw-r--r--ironic/conf/iscsi.py44
-rw-r--r--ironic/conf/opts.py1
-rw-r--r--ironic/db/api.py12
-rw-r--r--ironic/db/sqlalchemy/api.py53
-rw-r--r--ironic/drivers/generic.py7
-rw-r--r--ironic/drivers/modules/agent_client.py28
-rw-r--r--ironic/drivers/modules/iscsi_deploy.py813
-rw-r--r--ironic/objects/conductor.py2
-rw-r--r--ironic/tests/base.py2
-rw-r--r--ironic/tests/unit/api/controllers/v1/test_driver.py8
-rw-r--r--ironic/tests/unit/common/test_hash_ring.py6
-rw-r--r--ironic/tests/unit/conductor/test_base_manager.py14
-rw-r--r--ironic/tests/unit/conductor/test_manager.py4
-rw-r--r--ironic/tests/unit/conductor/test_rpcapi.py14
-rw-r--r--ironic/tests/unit/db/test_api.py70
-rw-r--r--ironic/tests/unit/db/test_conductor.py14
-rw-r--r--ironic/tests/unit/drivers/modules/ilo/test_boot.py2
-rw-r--r--ironic/tests/unit/drivers/modules/ilo/test_management.py2
-rw-r--r--ironic/tests/unit/drivers/modules/ilo/test_raid.py2
-rw-r--r--ironic/tests/unit/drivers/modules/test_agent_client.py40
-rw-r--r--ironic/tests/unit/drivers/modules/test_iscsi_deploy.py1816
-rw-r--r--ironic/tests/unit/drivers/modules/test_pxe.py3
-rw-r--r--ironic/tests/unit/objects/test_conductor.py4
-rw-r--r--releasenotes/notes/bye-bye-iscsi-658920cf126db0b8.yaml5
-rw-r--r--setup.cfg1
57 files changed, 116 insertions, 4455 deletions
diff --git a/api-ref/source/samples/driver-get-response.json b/api-ref/source/samples/driver-get-response.json
index 87cbcb1d3..14175beab 100644
--- a/api-ref/source/samples/driver-get-response.json
+++ b/api-ref/source/samples/driver-get-response.json
@@ -2,7 +2,7 @@
"default_bios_interface": "no-bios",
"default_boot_interface": "pxe",
"default_console_interface": "no-console",
- "default_deploy_interface": "iscsi",
+ "default_deploy_interface": "direct",
"default_inspect_interface": "no-inspect",
"default_management_interface": "ipmitool",
"default_network_interface": "flat",
@@ -21,7 +21,7 @@
"no-console"
],
"enabled_deploy_interfaces": [
- "iscsi",
+ "ansible",
"direct"
],
"enabled_inspect_interfaces": [
diff --git a/api-ref/source/samples/drivers-list-detail-response.json b/api-ref/source/samples/drivers-list-detail-response.json
index d3d93c8ce..3ba03200b 100644
--- a/api-ref/source/samples/drivers-list-detail-response.json
+++ b/api-ref/source/samples/drivers-list-detail-response.json
@@ -106,7 +106,7 @@
"default_bios_interface": "no-bios",
"default_boot_interface": "pxe",
"default_console_interface": "no-console",
- "default_deploy_interface": "iscsi",
+ "default_deploy_interface": "direct",
"default_inspect_interface": "no-inspect",
"default_management_interface": "ipmitool",
"default_network_interface": "flat",
@@ -125,7 +125,7 @@
"no-console"
],
"enabled_deploy_interfaces": [
- "iscsi",
+ "ansible",
"direct"
],
"enabled_inspect_interfaces": [
diff --git a/api-ref/source/samples/nodes-list-details-response.json b/api-ref/source/samples/nodes-list-details-response.json
index 98c22aa9a..70451eee2 100644
--- a/api-ref/source/samples/nodes-list-details-response.json
+++ b/api-ref/source/samples/nodes-list-details-response.json
@@ -119,7 +119,7 @@
"console_enabled": false,
"console_interface": "no-console",
"created_at": "2016-08-18T22:28:48.643434+11:11",
- "deploy_interface": "iscsi",
+ "deploy_interface": "direct",
"deploy_step": {},
"driver": "ipmi",
"driver_info": {
diff --git a/bindep.txt b/bindep.txt
index 2538b79c8..f88618df9 100644
--- a/bindep.txt
+++ b/bindep.txt
@@ -2,7 +2,6 @@
ipmitool [default]
ipxe [platform:dpkg default]
ipxe-bootimgs [platform:rpm default]
-open-iscsi [platform:dpkg default]
socat [default]
xinetd [default]
tftpd-hpa [platform:dpkg default]
diff --git a/doc/source/admin/drivers.rst b/doc/source/admin/drivers.rst
index 7df4dc6ad..c3d8eb377 100644
--- a/doc/source/admin/drivers.rst
+++ b/doc/source/admin/drivers.rst
@@ -76,7 +76,7 @@ not compatible with them. There are three ways to deal with this situation:
baremetal node set test --driver ipmi \
--boot-interface pxe \
- --deploy-interface iscsi \
+ --deploy-interface direct \
--management-interface ipmitool \
--power-interface ipmitool
diff --git a/doc/source/admin/drivers/ibmc.rst b/doc/source/admin/drivers/ibmc.rst
index 84786df02..1bf9a3ba2 100644
--- a/doc/source/admin/drivers/ibmc.rst
+++ b/doc/source/admin/drivers/ibmc.rst
@@ -312,15 +312,6 @@ boot_up_seq GET Query boot up sequence
get_raid_controller_list GET Query RAID controller summary info
======================== ============ ======================================
-
-PXE Boot and iSCSI Deploy Process with Ironic Standalone Environment
-====================================================================
-
-.. figure:: ../../images/ironic_standalone_with_ibmc_driver.svg
- :width: 960px
- :align: left
- :alt: Ironic standalone with iBMC driver node
-
.. _Huawei iBMC: https://e.huawei.com/en/products/cloud-computing-dc/servers/accessories/ibmc
.. _TLS: https://en.wikipedia.org/wiki/Transport_Layer_Security
.. _HUAWEI iBMC Client library: https://pypi.org/project/python-ibmcclient/
diff --git a/doc/source/admin/drivers/idrac.rst b/doc/source/admin/drivers/idrac.rst
index d1a1cb59f..8f37514c3 100644
--- a/doc/source/admin/drivers/idrac.rst
+++ b/doc/source/admin/drivers/idrac.rst
@@ -96,7 +96,7 @@ Interface Supported Implementations
``bios`` ``idrac-wsman``, ``idrac-redfish``, ``no-bios``
``boot`` ``ipxe``, ``pxe``, ``idrac-redfish-virtual-media``
``console`` ``no-console``
-``deploy`` ``iscsi``, ``direct``, ``ansible``, ``ramdisk``
+``deploy`` ``direct``, ``ansible``, ``ramdisk``
``inspect`` ``idrac-wsman``, ``idrac``, ``idrac-redfish``,
``inspector``, ``no-inspect``
``management`` ``idrac-wsman``, ``idrac``, ``idrac-redfish``
diff --git a/doc/source/admin/drivers/ilo.rst b/doc/source/admin/drivers/ilo.rst
index f82ed3ec5..838a3cb97 100644
--- a/doc/source/admin/drivers/ilo.rst
+++ b/doc/source/admin/drivers/ilo.rst
@@ -1097,8 +1097,9 @@ Netboot with glance and swift
IPA -> Conductor [label = "Lookup node"];
Conductor -> IPA [label = "Provides node UUID"];
IPA -> Conductor [label = "Heartbeat"];
- Conductor -> IPA [label = "Exposes the disk over iSCSI"];
- Conductor -> Conductor [label = "Connects to bare metal's disk over iSCSI and writes image"];
+ Conductor -> IPA [label = "Sends the user image HTTP(S) URL"];
+ IPA -> Swift [label = "Retrieves the user image on bare metal"];
+ IPA -> IPA [label = "Writes user image to disk"];
Conductor -> Conductor [label = "Generates the boot ISO"];
Conductor -> Swift [label = "Uploads the boot ISO"];
Conductor -> Conductor [label = "Generates swift tempURL for boot ISO"];
@@ -1222,8 +1223,9 @@ Netboot in swiftless deploy for intermediate images
IPA -> Conductor [label = "Lookup node"];
Conductor -> IPA [label = "Provides node UUID"];
IPA -> Conductor [label = "Heartbeat"];
- Conductor -> IPA [label = "Exposes the disk over iSCSI"];
- Conductor -> Conductor [label = "Connects to bare metal's disk over iSCSI and writes image"];
+ Conductor -> IPA [label = "Sends the user image HTTP(S) URL"];
+ IPA -> ConductorWebserver [label = "Retrieves the user image on bare metal"];
+ IPA -> IPA [label = "Writes user image to root partition"];
Conductor -> Conductor [label = "Generates the boot ISO"];
Conductor -> ConductorWebserver [label = "Uploads the boot ISO"];
Conductor -> iLO [label = "Attaches boot ISO URL as virtual media CDROM"];
@@ -1303,8 +1305,9 @@ Netboot with HTTP(S) based deploy
IPA -> Conductor [label = "Lookup node"];
Conductor -> IPA [label = "Provides node UUID"];
IPA -> Conductor [label = "Heartbeat"];
- Conductor -> IPA [label = "Exposes the disk over iSCSI"];
- Conductor -> Conductor [label = "Connects to bare metal's disk over iSCSI and writes image"];
+ Conductor -> IPA [label = "Sends the user image HTTP(S) URL"];
+ IPA -> Swift [label = "Retrieves the user image on bare metal"];
+ IPA -> IPA [label = "Writes user image to disk"];
Conductor -> Conductor [label = "Generates the boot ISO"];
Conductor -> Swift [label = "Uploads the boot ISO"];
Conductor -> Conductor [label = "Generates swift tempURL for boot ISO"];
@@ -1381,8 +1384,9 @@ Netboot in standalone ironic
IPA -> Conductor [label = "Lookup node"];
Conductor -> IPA [label = "Provides node UUID"];
IPA -> Conductor [label = "Heartbeat"];
- Conductor -> IPA [label = "Exposes the disk over iSCSI"];
- Conductor -> Conductor [label = "Connects to bare metal's disk over iSCSI and writes image"];
+ Conductor -> IPA [label = "Sends the user image HTTP(S) URL"];
+ IPA -> ConductorWebserver [label = "Retrieves the user image on bare metal"];
+ IPA -> IPA [label = "Writes user image to root partition"];
Conductor -> Conductor [label = "Generates the boot ISO"];
Conductor -> ConductorWebserver [label = "Uploads the boot ISO"];
Conductor -> iLO [label = "Attaches boot ISO URL as virtual media CDROM"];
diff --git a/doc/source/admin/drivers/ipa.rst b/doc/source/admin/drivers/ipa.rst
index 2fea3f9c8..ecafa081f 100644
--- a/doc/source/admin/drivers/ipa.rst
+++ b/doc/source/admin/drivers/ipa.rst
@@ -17,26 +17,11 @@ For more information see the
Drivers
=======
-Starting with the Kilo release all deploy interfaces (except for fake ones)
-are using IPA. There are two types of them:
-
-* For nodes using the :ref:`iscsi-deploy` interface, IPA exposes the root hard
- drive as an iSCSI share and calls back to the ironic conductor. The
- conductor mounts the share and copies an image there. It then signals back
- to IPA for post-installation actions like setting up a bootloader for local
- boot support.
-
-* For nodes using the :ref:`direct-deploy` interface, the conductor prepares
- a swift temporary URL for an image. IPA then handles the whole deployment
- process: downloading an image from swift, putting it on the machine and doing
- any post-deploy actions.
-
-Which one to choose depends on your environment. :ref:`iscsi-deploy` puts
-higher load on conductors, :ref:`direct-deploy` currently requires the whole
-image to fit in the node's memory, except when using raw images. It also
-requires :doc:`/install/configure-glance-swift`.
-
-.. todo: other differences?
+Starting with the Kilo release all deploy interfaces (except for fake ones) are
+using IPA. For nodes using the :ref:`direct-deploy` interface, the conductor
+prepares a swift temporary URL or a local HTTP URL for the image. IPA then
+handles the whole deployment process: downloading an image from swift, putting
+it on the machine and doing any post-deploy actions.
Requirements
------------
diff --git a/doc/source/admin/drivers/irmc.rst b/doc/source/admin/drivers/irmc.rst
index 460a59b75..3b388c338 100644
--- a/doc/source/admin/drivers/irmc.rst
+++ b/doc/source/admin/drivers/irmc.rst
@@ -88,7 +88,7 @@ interfaces enabled for ``irmc`` hardware type.
enabled_bios_interfaces = irmc
enabled_boot_interfaces = irmc-virtual-media,irmc-pxe
enabled_console_interfaces = ipmitool-socat,ipmitool-shellinabox,no-console
- enabled_deploy_interfaces = iscsi,direct
+ enabled_deploy_interfaces = direct
enabled_inspect_interfaces = irmc,inspector,no-inspect
enabled_management_interfaces = irmc
enabled_network_interfaces = flat,neutron
diff --git a/doc/source/admin/interfaces/boot.rst b/doc/source/admin/interfaces/boot.rst
index 2b74b17de..aa87dae1f 100644
--- a/doc/source/admin/interfaces/boot.rst
+++ b/doc/source/admin/interfaces/boot.rst
@@ -24,8 +24,8 @@ common, and usually requires bootstrapping using PXE first.
The ``pxe`` boot interface works by preparing a PXE/iPXE environment for a
node on the file system, then instructing the DHCP provider (for example,
the Networking service) to boot the node from it. See
-:ref:`iscsi-deploy-example` and :ref:`direct-deploy-example` for a better
-understanding of the whole deployment process.
+ref:`direct-deploy-example` for a better understanding of the whole deployment
+process.
.. note::
Both PXE and iPXE are configured differently, when UEFI boot is used
diff --git a/doc/source/admin/interfaces/deploy.rst b/doc/source/admin/interfaces/deploy.rst
index aaac9245e..f2aceb3bd 100644
--- a/doc/source/admin/interfaces/deploy.rst
+++ b/doc/source/admin/interfaces/deploy.rst
@@ -105,7 +105,7 @@ section of ironic's configuration file:
[DEFAULT]
...
- enabled_deploy_interfaces = iscsi,direct,ansible
+ enabled_deploy_interfaces = direct,ansible
...
Once enabled, you can specify this deploy interface when creating or updating
@@ -133,26 +133,3 @@ Ramdisk deploy
The ramdisk interface is intended to provide a mechanism to "deploy" an
instance where the item to be deployed is in reality a ramdisk. It is
documented separately, see :doc:`/admin/ramdisk-boot`.
-
-.. _iscsi-deploy:
-
-iSCSI deploy
-============
-
-.. warning::
- This deploy interface is deprecated and will be removed in the Xena release
- cycle. Please use `direct deploy`_ instead.
-
-With ``iscsi`` deploy interface, the deploy ramdisk publishes the node's hard
-drive as an iSCSI_ share. The ironic-conductor then copies the image to this
-share. See :ref:`iSCSI deploy diagram <iscsi-deploy-example>` for a detailed
-explanation of how this deploy interface works.
-
-This interface is used by default, if enabled (see
-:ref:`enable-hardware-interfaces`). You can specify it explicitly
-when creating or updating a node::
-
- baremetal node create --driver ipmi --deploy-interface iscsi
- baremetal node set <NODE> --deploy-interface iscsi
-
-.. _iSCSI: https://en.wikipedia.org/wiki/ISCSI
diff --git a/doc/source/admin/node-deployment.rst b/doc/source/admin/node-deployment.rst
index 421edc179..5ca95567b 100644
--- a/doc/source/admin/node-deployment.rst
+++ b/doc/source/admin/node-deployment.rst
@@ -41,13 +41,13 @@ BIOS, and RAID interfaces.
Agent steps
-----------
-All deploy interfaces based on ironic-python-agent (i.e. ``direct``, ``iscsi``
-and ``ansible`` and any derivatives) expose the following deploy steps:
+All deploy interfaces based on ironic-python-agent (i.e. ``direct``,
+``ansible`` and any derivatives) expose the following deploy steps:
``deploy.deploy`` (priority 100)
In this step the node is booted using a provisioning image.
``deploy.write_image`` (priority 80)
- An out-of-band (``iscsi``, ``ansible``) or in-band (``direct``) step that
+ An out-of-band (``ansible``) or in-band (``direct``) step that
downloads and writes the image to the node.
``deploy.tear_down_agent`` (priority 40)
In this step the provisioning image is shut down.
@@ -57,7 +57,7 @@ and ``ansible`` and any derivatives) expose the following deploy steps:
``deploy.boot_instance`` (priority 20)
In this step the node is booted into the user image.
-Additionally, the ``iscsi`` and ``direct`` deploy interfaces have:
+Additionally, the ``direct`` deploy interfaces has:
``deploy.prepare_instance_boot`` (priority 60)
In this step the boot device is configured and the bootloader is installed.
diff --git a/doc/source/admin/notifications.rst b/doc/source/admin/notifications.rst
index 2f83e6483..bf299d66f 100644
--- a/doc/source/admin/notifications.rst
+++ b/doc/source/admin/notifications.rst
@@ -210,7 +210,7 @@ Example of node CRUD notification::
"bios_interface": "no-bios",
"boot_interface": "pxe",
"console_interface": "no-console",
- "deploy_interface": "iscsi",
+ "deploy_interface": "direct",
"inspect_interface": "no-inspect",
"management_interface": "ipmitool",
"network_interface": "flat",
@@ -444,7 +444,7 @@ node maintenance notification::
"bios_interface": "no-bios",
"boot_interface": "pxe",
"console_interface": "no-console",
- "deploy_interface": "iscsi",
+ "deploy_interface": "direct",
"inspect_interface": "no-inspect",
"management_interface": "ipmitool",
"network_interface": "flat",
@@ -534,7 +534,7 @@ level, "error" has ERROR. Example of node console notification::
"bios_interface": "no-bios",
"boot_interface": "pxe",
"console_interface": "no-console",
- "deploy_interface": "iscsi",
+ "deploy_interface": "direct",
"inspect_interface": "no-inspect",
"management_interface": "ipmitool",
"network_interface": "flat",
@@ -617,7 +617,7 @@ ironic-conductor is attempting to change the node::
"bios_interface": "no-bios",
"boot_interface": "pxe",
"console_interface": "no-console",
- "deploy_interface": "iscsi",
+ "deploy_interface": "direct",
"inspect_interface": "no-inspect",
"management_interface": "ipmitool",
"network_interface": "flat",
@@ -695,7 +695,7 @@ prior to the correction::
"bios_interface": "no-bios",
"boot_interface": "pxe",
"console_interface": "no-console",
- "deploy_interface": "iscsi",
+ "deploy_interface": "direct",
"inspect_interface": "no-inspect",
"management_interface": "ipmitool",
"network_interface": "flat",
@@ -787,7 +787,7 @@ indicate a node's provision states before state change, "event" is the FSM
"bios_interface": "no-bios",
"boot_interface": "pxe",
"console_interface": "no-console",
- "deploy_interface": "iscsi",
+ "deploy_interface": "direct",
"inspect_interface": "no-inspect",
"management_interface": "ipmitool",
"network_interface": "flat",
diff --git a/doc/source/admin/ramdisk-boot.rst b/doc/source/admin/ramdisk-boot.rst
index b24f86881..d961b21ab 100644
--- a/doc/source/admin/ramdisk-boot.rst
+++ b/doc/source/admin/ramdisk-boot.rst
@@ -18,7 +18,7 @@ non-default interfaces, it must be enabled and set for a node to be utilized:
[DEFAULT]
...
- enabled_deploy_interfaces = iscsi,direct,ramdisk
+ enabled_deploy_interfaces = direct,ramdisk
...
Once enabled and the conductor(s) have been restarted, the interface can
diff --git a/doc/source/admin/troubleshooting.rst b/doc/source/admin/troubleshooting.rst
index acbcdea76..c7347cbd8 100644
--- a/doc/source/admin/troubleshooting.rst
+++ b/doc/source/admin/troubleshooting.rst
@@ -420,13 +420,10 @@ Overall:
timers to help ensure a deployment does not fail due to a short-lived
transitory network connectivity failure in the form of a switch port having
moved to a temporary blocking state. Where applicable and possible,
- many of these patches have been backported to supported releases,
- however users of the iSCSI deployment interface will see the least
- capability for these sorts of situations to be handled
- automatically. These patches also require that the switchport has an
- eventual fallback to a non-bonded mode. If the port remains in a blocking
- state, then traffic will be unable to flow and the deloyment is likely to
- time out.
+ many of these patches have been backported to supported releases.
+ These patches also require that the switchport has an eventual fallback to a
+ non-bonded mode. If the port remains in a blocking state, then traffic will
+ be unable to flow and the deployment is likely to time out.
* If you must use LACP, consider ``passive`` LACP negotiation settings
in the network switch as opposed to ``active``. The difference being with
passive the connected workload is likely a server where it should likely
@@ -543,16 +540,10 @@ Again, these sorts of cases will depend upon the exact configuration of the
deployment, but hopefully these are areas where these actions can occur.
* Conversion to raw image files upon download to the conductor, from the
- ``[DEFAULT]force_raw_images`` option, in particular with the ``iscsi``
- deployment interface. Users using glance and the ``direct`` deployment
- interface may also experience issues here as the conductor will cache
- the image to be written which takes place when the
- ``[agent]image_download_source`` is set to ``http`` instead of ``swift``.
-
-* Write of a QCOW2 file over the ``iscsi`` deployment interface from the
- conductor to the node being deployed can result in large amounts of
- "white space" to be written to be transmitted over the wire and written
- to the end device.
+ ``[DEFAULT]force_raw_images`` option. Users using Glance may also experience
+ issues here as the conductor will cache the image to be written which takes
+ place when the ``[agent]image_download_source`` is set to ``http`` instead of
+ ``swift``.
.. note::
The QCOW2 image conversion utility does consume quite a bit of memory
@@ -560,9 +551,8 @@ deployment, but hopefully these are areas where these actions can occur.
is because the files are not sequential in nature, and must be re-assembled
from an internal block mapping. Internally Ironic limits this to 1GB
of RAM. Operators performing large numbers of deployments may wish to
- explore the ``direct`` deployment interface in these sorts of cases in
- order to minimize the conductor becoming a limiting factor due to memory
- and network IO.
+ disable raw images in these sorts of cases in order to minimize the
+ conductor becoming a limiting factor due to memory and network IO.
Why are my nodes stuck in a "wait" state?
=========================================
diff --git a/doc/source/admin/tuning.rst b/doc/source/admin/tuning.rst
index 02636e608..b554d76ea 100644
--- a/doc/source/admin/tuning.rst
+++ b/doc/source/admin/tuning.rst
@@ -10,7 +10,7 @@ be asked by API consumers to perform work for which the underlying tools
require large amounts of memory.
The biggest example of this is image conversion. Images not in a raw format
-need to be written out to disk (local files or remote in iscsi deploy) which
+need to be written out to disk for conversion (when requested) which
requires the conversion process to generate an in-memory map to re-assemble
the image contents into a coherent stream of data. This entire process also
stresses the kernel buffers and cache.
diff --git a/doc/source/contributor/dev-quickstart.rst b/doc/source/contributor/dev-quickstart.rst
index 84638c61b..639999115 100644
--- a/doc/source/contributor/dev-quickstart.rst
+++ b/doc/source/contributor/dev-quickstart.rst
@@ -420,8 +420,8 @@ Ironic
------
Create devstack/local.conf with minimal settings required to enable Ironic.
-An example local.conf that enables both ``direct`` and ``iscsi``
-:doc:`deploy interfaces </admin/interfaces/deploy>` and uses the ``ipmi``
+An example local.conf that enables the ``direct``
+:doc:`deploy interface </admin/interfaces/deploy>` and uses the ``ipmi``
hardware type by default::
cd devstack
@@ -468,8 +468,6 @@ hardware type by default::
# interfaces, most often power and management:
#IRONIC_ENABLED_MANAGEMENT_INTERFACES=ipmitool,fake
#IRONIC_ENABLED_POWER_INTERFACES=ipmitool,fake
- # The 'ipmi' hardware type's default deploy interface is 'iscsi'.
- # This would change the default to 'direct':
#IRONIC_DEFAULT_DEPLOY_INTERFACE=direct
# Change this to alter the default driver for nodes created by devstack.
@@ -516,9 +514,8 @@ directory you cloned DevStack::
An example local.conf that enables the ironic tempest plugin and Ironic can be
found below. The ``TEMPEST_PLUGINS`` variable needs to have the absolute path
to the ironic-tempest-plugin folder, otherwise the plugin won't be installed.
-Ironic will have enabled both ``direct`` and
-``iscsi`` :doc:`deploy interfaces </admin/interfaces/deploy>` and uses the
-``ipmi`` hardware type by default::
+Ironic will have enabled the ``direct`` :doc:`deploy interface
+</admin/interfaces/deploy>` and uses the ``ipmi`` hardware type by default::
cd devstack
cat >local.conf <<END
@@ -564,8 +561,6 @@ Ironic will have enabled both ``direct`` and
# interfaces, most often power and management:
#IRONIC_ENABLED_MANAGEMENT_INTERFACES=ipmitool,fake
#IRONIC_ENABLED_POWER_INTERFACES=ipmitool,fake
- # The 'ipmi' hardware type's default deploy interface is 'iscsi'.
- # This would change the default to 'direct':
#IRONIC_DEFAULT_DEPLOY_INTERFACE=direct
# Change this to alter the default driver for nodes created by devstack.
diff --git a/doc/source/contributor/ironic-boot-from-volume.rst b/doc/source/contributor/ironic-boot-from-volume.rst
index 2a3d3da53..359489623 100644
--- a/doc/source/contributor/ironic-boot-from-volume.rst
+++ b/doc/source/contributor/ironic-boot-from-volume.rst
@@ -69,7 +69,6 @@ description for DevStack is at :ref:`deploy_devstack`.
# interfaces, most often power and management:
#IRONIC_ENABLED_MANAGEMENT_INTERFACES=ipmitool,fake
#IRONIC_ENABLED_POWER_INTERFACES=ipmitool,fake
- # The default deploy interface is 'iscsi', you can use 'direct' with
#IRONIC_DEFAULT_DEPLOY_INTERFACE=direct
# Change this to alter the default driver for nodes created by devstack.
diff --git a/doc/source/contributor/ironic-multitenant-networking.rst b/doc/source/contributor/ironic-multitenant-networking.rst
index da7225bcf..36d4125e9 100644
--- a/doc/source/contributor/ironic-multitenant-networking.rst
+++ b/doc/source/contributor/ironic-multitenant-networking.rst
@@ -93,7 +93,6 @@ configured in Neutron.
# interfaces, most often power and management:
#IRONIC_ENABLED_MANAGEMENT_INTERFACES=ipmitool,fake
#IRONIC_ENABLED_POWER_INTERFACES=ipmitool,fake
- # The default deploy interface is 'iscsi', you can use 'direct' with
#IRONIC_DEFAULT_DEPLOY_INTERFACE=direct
# Change this to alter the default driver for nodes created by devstack.
diff --git a/doc/source/images/ironic_standalone_with_ibmc_driver.svg b/doc/source/images/ironic_standalone_with_ibmc_driver.svg
deleted file mode 100644
index d2ef253e2..000000000
--- a/doc/source/images/ironic_standalone_with_ibmc_driver.svg
+++ /dev/null
@@ -1,1309 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.2" width="210.06mm" height="296.93mm" viewBox="0 0 21006 29693" preserveAspectRatio="xMidYMid" fill-rule="evenodd" stroke-width="28.222" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" xmlns:ooo="http://xml.openoffice.org/svg/export" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:presentation="http://sun.com/xmlns/staroffice/presentation" xmlns:smil="http://www.w3.org/2001/SMIL20/" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" xml:space="preserve">
- <defs class="ClipPathGroup">
- <clipPath id="presentation_clip_path" clipPathUnits="userSpaceOnUse">
- <rect x="0" y="0" width="21006" height="29693"/>
- </clipPath>
- </defs>
- <defs>
- <font id="EmbeddedFont_1" horiz-adv-x="2048">
- <font-face font-family="Liberation Sans embedded" units-per-em="2048" font-weight="normal" font-style="normal" ascent="1852" descent="423"/>
- <missing-glyph horiz-adv-x="2048" d="M 0,0 L 2047,0 2047,2047 0,2047 0,0 Z"/>
- <glyph unicode="y" horiz-adv-x="1033" d="M 604,1 C 579,-64 553,-123 527,-175 500,-227 471,-272 438,-309 405,-346 369,-374 329,-394 289,-413 243,-423 191,-423 168,-423 147,-423 128,-423 109,-423 88,-420 67,-414 L 67,-279 C 80,-282 94,-284 110,-284 126,-284 140,-284 151,-284 204,-284 253,-264 298,-225 343,-186 383,-124 417,-38 L 434,5 5,1082 197,1082 425,484 C 432,466 440,442 451,412 461,382 471,352 482,322 492,292 501,265 509,241 517,217 522,202 523,196 525,203 530,218 538,240 545,261 554,285 564,312 573,339 583,366 593,393 603,420 611,444 618,464 L 830,1082 1020,1082 604,1 Z"/>
- <glyph unicode="x" horiz-adv-x="1006" d="M 801,0 L 510,444 217,0 23,0 408,556 41,1082 240,1082 510,661 778,1082 979,1082 612,558 1002,0 801,0 Z"/>
- <glyph unicode="w" horiz-adv-x="1509" d="M 1174,0 L 965,0 792,698 C 787,716 781,738 776,765 770,792 764,818 759,843 752,872 746,903 740,934 734,904 728,874 721,845 716,820 710,793 704,766 697,739 691,715 686,694 L 508,0 300,0 -3,1082 175,1082 358,347 C 363,332 367,313 372,291 377,268 381,246 386,225 391,200 396,175 401,149 406,174 412,199 418,223 423,244 429,265 434,286 439,307 444,325 448,339 L 644,1082 837,1082 1026,339 C 1031,322 1036,302 1041,280 1046,258 1051,237 1056,218 1061,195 1067,172 1072,149 1077,174 1083,199 1088,223 1093,244 1098,265 1103,288 1108,310 1112,330 1117,347 L 1308,1082 1484,1082 1174,0 Z"/>
- <glyph unicode="v" horiz-adv-x="1033" d="M 613,0 L 400,0 7,1082 199,1082 437,378 C 442,363 447,346 454,325 460,304 466,282 473,259 480,236 486,215 492,194 497,173 502,155 506,141 510,155 515,173 522,194 528,215 534,236 541,258 548,280 555,302 562,323 569,344 575,361 580,376 L 826,1082 1017,1082 613,0 Z"/>
- <glyph unicode="u" horiz-adv-x="874" d="M 314,1082 L 314,396 C 314,343 318,299 326,264 333,229 346,200 363,179 380,157 403,142 432,133 460,124 495,119 537,119 580,119 618,127 653,142 687,157 716,178 741,207 765,235 784,270 797,312 810,353 817,401 817,455 L 817,1082 997,1082 997,228 C 997,205 997,181 998,156 998,131 998,107 999,85 1000,62 1000,43 1001,27 1002,11 1002,3 1003,3 L 833,3 C 832,6 832,15 831,30 830,44 830,61 829,79 828,98 827,117 826,136 825,156 825,172 825,185 L 822,185 C 805,154 786,125 765,100 744,75 720,53 693,36 666,18 634,4 599,-6 564,-15 523,-20 476,-20 416,-20 364,-13 321,2 278,17 242,39 214,70 186,101 166,140 153,188 140,236 133,294 133,361 L 133,1082 314,1082 Z"/>
- <glyph unicode="t" horiz-adv-x="531" d="M 554,8 C 527,1 499,-5 471,-10 442,-14 409,-16 372,-16 228,-16 156,66 156,229 L 156,951 31,951 31,1082 163,1082 216,1324 336,1324 336,1082 536,1082 536,951 336,951 336,268 C 336,216 345,180 362,159 379,138 408,127 450,127 467,127 484,128 501,131 517,134 535,137 554,141 L 554,8 Z"/>
- <glyph unicode="s" horiz-adv-x="901" d="M 950,299 C 950,248 940,203 921,164 901,124 872,91 835,64 798,37 752,16 698,2 643,-13 581,-20 511,-20 448,-20 392,-15 342,-6 291,4 247,20 209,41 171,62 139,91 114,126 88,161 69,203 57,254 L 216,285 C 231,227 263,185 311,158 359,131 426,117 511,117 550,117 585,120 618,125 650,130 678,140 701,153 724,166 743,183 756,205 769,226 775,253 775,285 775,318 767,345 752,366 737,387 715,404 688,418 661,432 628,444 589,455 550,465 507,476 460,489 417,500 374,513 331,527 288,541 250,560 216,583 181,606 153,634 132,668 111,702 100,745 100,796 100,895 135,970 206,1022 276,1073 378,1099 513,1099 632,1099 727,1078 798,1036 868,994 912,927 931,834 L 769,814 C 763,842 752,866 736,885 720,904 701,919 678,931 655,942 630,951 602,956 573,961 544,963 513,963 432,963 372,951 333,926 294,901 275,864 275,814 275,785 282,761 297,742 311,723 331,707 357,694 382,681 413,669 449,660 485,650 525,640 568,629 597,622 626,614 656,606 686,597 715,587 744,576 772,564 799,550 824,535 849,519 870,500 889,478 908,456 923,430 934,401 945,372 950,338 950,299 Z"/>
- <glyph unicode="r" horiz-adv-x="530" d="M 142,0 L 142,830 C 142,853 142,876 142,900 141,923 141,946 140,968 139,990 139,1011 138,1030 137,1049 137,1067 136,1082 L 306,1082 C 307,1067 308,1049 309,1030 310,1010 311,990 312,969 313,948 313,929 314,910 314,891 314,874 314,861 L 318,861 C 331,902 344,938 359,969 373,999 390,1024 409,1044 428,1063 451,1078 478,1088 505,1097 537,1102 575,1102 590,1102 604,1101 617,1099 630,1096 641,1094 648,1092 L 648,927 C 636,930 622,933 606,935 590,936 572,937 552,937 511,937 476,928 447,909 418,890 394,865 376,832 357,799 344,759 335,714 326,668 322,618 322,564 L 322,0 142,0 Z"/>
- <glyph unicode="q" horiz-adv-x="927" d="M 484,-20 C 347,-20 246,26 182,119 118,212 86,351 86,536 86,724 119,865 185,960 250,1055 350,1102 484,1102 529,1102 568,1098 603,1090 637,1082 668,1070 695,1055 722,1039 745,1019 766,996 786,973 804,945 821,914 L 823,914 C 823,931 824,949 825,970 826,990 827,1010 828,1028 829,1046 830,1061 831,1074 832,1087 834,1094 835,1094 L 1008,1094 C 1007,1083 1005,1053 1004,1005 1002,957 1001,889 1001,799 L 1001,-425 821,-425 821,14 C 821,31 821,49 822,68 822,87 822,104 823,121 824,140 824,159 825,178 L 823,178 C 806,144 787,115 766,90 745,65 720,44 693,28 666,11 635,-1 601,-9 566,-16 527,-20 484,-20 Z M 821,554 C 821,633 814,699 801,752 787,805 768,848 743,880 718,912 687,935 652,949 616,962 576,969 532,969 486,969 447,961 414,944 381,927 355,901 335,866 314,831 299,786 290,733 280,679 275,615 275,542 275,470 280,407 289,354 298,301 312,257 333,222 353,187 379,162 412,145 444,128 483,119 530,119 570,119 608,125 643,138 678,150 709,172 736,205 762,237 783,281 798,338 813,394 821,466 821,554 Z"/>
- <glyph unicode="p" horiz-adv-x="953" d="M 1053,546 C 1053,464 1046,388 1033,319 1020,250 998,190 967,140 936,90 895,51 844,23 793,-6 730,-20 655,-20 578,-20 510,-5 452,24 394,53 350,101 319,168 L 314,168 C 315,167 315,161 316,150 316,139 316,126 317,110 317,94 317,76 318,57 318,37 318,17 318,-2 L 318,-425 138,-425 138,864 C 138,891 138,916 138,940 137,964 137,986 136,1005 135,1025 135,1042 134,1056 133,1070 133,1077 132,1077 L 306,1077 C 307,1075 308,1068 309,1057 310,1045 311,1031 312,1014 313,998 314,980 315,961 316,943 316,925 316,908 L 320,908 C 337,943 356,972 377,997 398,1021 423,1041 450,1057 477,1072 508,1084 542,1091 575,1098 613,1101 655,1101 730,1101 793,1088 844,1061 895,1034 936,997 967,949 998,900 1020,842 1033,774 1046,705 1053,629 1053,546 Z M 864,542 C 864,609 860,668 852,720 844,772 830,816 811,852 791,888 765,915 732,934 699,953 658,962 609,962 569,962 531,956 496,945 461,934 430,912 404,880 377,848 356,804 341,748 326,691 318,618 318,528 318,451 324,387 337,334 350,281 368,238 393,205 417,172 447,149 483,135 519,120 560,113 607,113 657,113 699,123 732,142 765,161 791,189 811,226 830,263 844,308 852,361 860,414 864,474 864,542 Z"/>
- <glyph unicode="o" horiz-adv-x="980" d="M 1053,542 C 1053,353 1011,212 928,119 845,26 724,-20 565,-20 490,-20 422,-9 363,14 304,37 254,71 213,118 172,165 140,223 119,294 97,364 86,447 86,542 86,915 248,1102 571,1102 655,1102 728,1090 789,1067 850,1044 900,1009 939,962 978,915 1006,857 1025,787 1044,717 1053,635 1053,542 Z M 864,542 C 864,626 858,695 845,750 832,805 813,848 788,881 763,914 732,937 696,950 660,963 619,969 574,969 528,969 487,962 450,949 413,935 381,912 355,879 329,846 309,802 296,747 282,692 275,624 275,542 275,458 282,389 297,334 312,279 332,235 358,202 383,169 414,146 449,133 484,120 522,113 563,113 609,113 651,120 688,133 725,146 757,168 783,201 809,234 829,278 843,333 857,388 864,458 864,542 Z"/>
- <glyph unicode="n" horiz-adv-x="874" d="M 825,0 L 825,686 C 825,739 821,783 814,818 806,853 793,882 776,904 759,925 736,941 708,950 679,959 644,963 602,963 559,963 521,956 487,941 452,926 423,904 399,876 374,847 355,812 342,771 329,729 322,681 322,627 L 322,0 142,0 142,853 C 142,876 142,900 142,925 141,950 141,974 140,996 139,1019 139,1038 138,1054 137,1070 137,1078 136,1078 L 306,1078 C 307,1075 307,1066 308,1052 309,1037 310,1021 311,1002 312,984 312,965 313,945 314,926 314,910 314,897 L 317,897 C 334,928 353,957 374,982 395,1007 419,1029 446,1047 473,1064 505,1078 540,1088 575,1097 616,1102 663,1102 723,1102 775,1095 818,1080 861,1065 897,1043 925,1012 953,981 974,942 987,894 1000,845 1006,788 1006,721 L 1006,0 825,0 Z"/>
- <glyph unicode="m" horiz-adv-x="1457" d="M 768,0 L 768,686 C 768,739 765,783 758,818 751,853 740,882 725,904 709,925 688,941 663,950 638,959 607,963 570,963 532,963 498,956 467,941 436,926 410,904 389,876 367,847 350,812 339,771 327,729 321,681 321,627 L 321,0 142,0 142,853 C 142,876 142,900 142,925 141,950 141,974 140,996 139,1019 139,1038 138,1054 137,1070 137,1078 136,1078 L 306,1078 C 307,1075 307,1066 308,1052 309,1037 310,1021 311,1002 312,984 312,965 313,945 314,926 314,910 314,897 L 317,897 C 333,928 350,957 369,982 388,1007 410,1029 435,1047 460,1064 488,1078 521,1088 553,1097 590,1102 633,1102 715,1102 780,1086 828,1053 875,1020 908,968 927,897 L 930,897 C 946,928 964,957 984,982 1004,1007 1027,1029 1054,1047 1081,1064 1111,1078 1144,1088 1177,1097 1215,1102 1258,1102 1313,1102 1360,1095 1400,1080 1439,1065 1472,1043 1497,1012 1522,981 1541,942 1553,894 1565,845 1571,788 1571,721 L 1571,0 1393,0 1393,686 C 1393,739 1390,783 1383,818 1376,853 1365,882 1350,904 1334,925 1313,941 1288,950 1263,959 1232,963 1195,963 1157,963 1123,956 1092,942 1061,927 1035,906 1014,878 992,850 975,815 964,773 952,731 946,682 946,627 L 946,0 768,0 Z"/>
- <glyph unicode="l" horiz-adv-x="187" d="M 138,0 L 138,1484 318,1484 318,0 138,0 Z"/>
- <glyph unicode="k" horiz-adv-x="901" d="M 816,0 L 450,494 318,385 318,0 138,0 138,1484 318,1484 318,557 793,1082 1004,1082 565,617 1027,0 816,0 Z"/>
- <glyph unicode="i" horiz-adv-x="187" d="M 137,1312 L 137,1484 317,1484 317,1312 137,1312 Z M 137,0 L 137,1082 317,1082 317,0 137,0 Z"/>
- <glyph unicode="h" horiz-adv-x="874" d="M 317,897 C 337,934 359,965 382,991 405,1016 431,1037 459,1054 487,1071 518,1083 551,1091 584,1098 622,1102 663,1102 732,1102 789,1093 834,1074 878,1055 913,1029 939,996 964,962 982,922 992,875 1001,828 1006,777 1006,721 L 1006,0 825,0 825,686 C 825,732 822,772 817,807 811,842 800,871 784,894 768,917 745,934 716,946 687,957 649,963 602,963 559,963 521,955 487,940 452,925 423,903 399,875 374,847 355,813 342,773 329,733 322,688 322,638 L 322,0 142,0 142,1484 322,1484 322,1098 C 322,1076 322,1054 321,1032 320,1010 320,990 319,971 318,952 317,937 316,924 315,911 315,902 314,897 L 317,897 Z"/>
- <glyph unicode="g" horiz-adv-x="927" d="M 548,-425 C 486,-425 431,-419 383,-406 335,-393 294,-375 260,-352 226,-328 198,-300 177,-267 156,-234 140,-198 131,-158 L 312,-132 C 324,-182 351,-220 392,-248 433,-274 486,-288 553,-288 594,-288 631,-282 664,-271 697,-260 726,-241 749,-217 772,-191 790,-159 803,-119 816,-79 822,-30 822,27 L 822,201 820,201 C 807,174 790,148 771,123 751,98 727,75 699,56 670,37 637,21 600,10 563,-2 520,-8 472,-8 403,-8 345,4 296,27 247,50 207,84 176,130 145,176 122,233 108,302 93,370 86,449 86,539 86,626 93,704 108,773 122,842 145,901 178,950 210,998 252,1035 304,1061 355,1086 418,1099 492,1099 569,1099 635,1082 692,1047 748,1012 791,962 822,897 L 824,897 C 824,914 825,933 826,953 827,974 828,994 829,1012 830,1031 831,1046 832,1060 833,1073 835,1080 836,1080 L 1007,1080 C 1006,1074 1006,1064 1005,1050 1004,1035 1004,1018 1003,998 1002,978 1002,956 1002,932 1001,907 1001,882 1001,856 L 1001,30 C 1001,-121 964,-234 890,-311 815,-387 701,-425 548,-425 Z M 822,541 C 822,616 814,681 798,735 781,788 760,832 733,866 706,900 676,925 642,941 607,957 572,965 536,965 490,965 451,957 418,941 385,925 357,900 336,866 314,831 298,787 288,734 277,680 272,616 272,541 272,463 277,398 288,345 298,292 314,249 335,216 356,183 383,160 416,146 449,132 488,125 533,125 569,125 604,133 639,148 673,163 704,188 731,221 758,254 780,297 797,350 814,403 822,466 822,541 Z"/>
- <glyph unicode="f" horiz-adv-x="557" d="M 361,951 L 361,0 181,0 181,951 29,951 29,1082 181,1082 181,1204 C 181,1243 185,1280 192,1314 199,1347 213,1377 233,1402 252,1427 279,1446 313,1461 347,1475 391,1482 445,1482 466,1482 489,1481 512,1479 535,1477 555,1474 572,1470 L 572,1333 C 561,1335 548,1337 533,1339 518,1340 504,1341 492,1341 465,1341 444,1337 427,1330 410,1323 396,1312 387,1299 377,1285 370,1268 367,1248 363,1228 361,1205 361,1179 L 361,1082 572,1082 572,951 361,951 Z"/>
- <glyph unicode="e" horiz-adv-x="980" d="M 276,503 C 276,446 282,394 294,347 305,299 323,258 348,224 372,189 403,163 441,144 479,125 525,115 578,115 656,115 719,131 766,162 813,193 844,233 861,281 L 1019,236 C 1008,206 992,176 972,146 951,115 924,88 890,64 856,39 814,19 763,4 712,-12 650,-20 578,-20 418,-20 296,28 213,123 129,218 87,360 87,548 87,649 100,735 125,806 150,876 185,933 229,977 273,1021 324,1053 383,1073 442,1092 504,1102 571,1102 662,1102 738,1087 799,1058 860,1029 909,988 946,937 983,885 1009,824 1025,754 1040,684 1048,608 1048,527 L 1048,503 276,503 Z M 862,641 C 852,755 823,838 775,891 727,943 658,969 568,969 538,969 507,964 474,955 441,945 410,928 382,903 354,878 330,845 311,803 292,760 281,706 278,641 L 862,641 Z"/>
- <glyph unicode="d" horiz-adv-x="927" d="M 821,174 C 788,105 744,55 689,25 634,-5 565,-20 484,-20 347,-20 247,26 183,118 118,210 86,349 86,536 86,913 219,1102 484,1102 566,1102 634,1087 689,1057 744,1027 788,979 821,914 L 823,914 C 823,921 823,931 823,946 822,960 822,975 822,991 821,1006 821,1021 821,1035 821,1049 821,1059 821,1065 L 821,1484 1001,1484 1001,219 C 1001,193 1001,168 1002,143 1002,119 1002,97 1003,77 1004,57 1004,40 1005,26 1006,11 1006,4 1007,4 L 835,4 C 834,11 833,20 832,32 831,44 830,58 829,73 828,89 827,105 826,123 825,140 825,157 825,174 L 821,174 Z M 275,542 C 275,467 280,403 289,350 298,297 313,253 334,219 355,184 381,159 413,143 445,127 484,119 530,119 577,119 619,127 656,142 692,157 722,182 747,217 771,251 789,296 802,351 815,406 821,474 821,554 821,631 815,696 802,749 789,802 771,844 746,877 721,910 691,933 656,948 620,962 579,969 532,969 488,969 450,961 418,946 386,931 359,906 338,872 317,838 301,794 291,740 280,685 275,619 275,542 Z"/>
- <glyph unicode="c" horiz-adv-x="901" d="M 275,546 C 275,484 280,427 289,375 298,323 313,278 334,241 355,203 384,174 419,153 454,132 497,122 548,122 612,122 666,139 709,173 752,206 778,258 788,328 L 970,328 C 964,283 951,239 931,197 911,155 884,118 850,86 815,54 773,28 724,9 675,-10 618,-20 553,-20 468,-20 396,-6 337,23 278,52 230,91 193,142 156,192 129,251 112,320 95,388 87,462 87,542 87,615 93,679 105,735 117,790 134,839 156,881 177,922 203,957 232,986 261,1014 293,1037 328,1054 362,1071 398,1083 436,1091 474,1098 512,1102 551,1102 612,1102 666,1094 713,1077 760,1060 801,1038 836,1009 870,980 898,945 919,906 940,867 955,824 964,779 L 779,765 C 770,825 746,873 708,908 670,943 616,961 546,961 495,961 452,953 418,936 383,919 355,893 334,859 313,824 298,781 289,729 280,677 275,616 275,546 Z"/>
- <glyph unicode="b" horiz-adv-x="953" d="M 1053,546 C 1053,169 920,-20 655,-20 573,-20 505,-5 451,25 396,54 352,102 318,168 L 316,168 C 316,150 316,132 315,113 314,94 313,77 312,61 311,45 310,31 309,19 308,8 307,2 306,2 L 132,2 C 133,8 133,18 134,32 135,47 135,64 136,84 137,104 137,126 138,150 138,174 138,199 138,225 L 138,1484 318,1484 318,1061 C 318,1041 318,1022 318,1004 317,985 317,969 316,955 315,938 315,923 314,908 L 318,908 C 351,977 396,1027 451,1057 506,1087 574,1102 655,1102 792,1102 892,1056 957,964 1021,872 1053,733 1053,546 Z M 864,540 C 864,615 859,679 850,732 841,785 826,829 805,864 784,898 758,923 726,939 694,955 655,963 609,963 562,963 520,955 484,940 447,925 417,900 393,866 368,832 350,787 337,732 324,677 318,609 318,529 318,452 324,387 337,334 350,281 368,239 393,206 417,173 447,149 483,135 519,120 560,113 607,113 651,113 689,121 721,136 753,151 780,176 801,210 822,244 838,288 849,343 859,397 864,463 864,540 Z"/>
- <glyph unicode="a" horiz-adv-x="1060" d="M 414,-20 C 305,-20 224,9 169,66 114,124 87,203 87,303 87,375 101,434 128,480 155,526 190,562 234,588 277,614 327,632 383,642 439,652 496,657 554,657 L 797,657 797,717 C 797,762 792,800 783,832 774,863 759,889 740,908 721,928 697,942 668,951 639,960 604,965 565,965 530,965 499,963 471,958 443,953 419,944 398,931 377,918 361,900 348,878 335,855 327,827 323,793 L 135,810 C 142,853 154,892 173,928 192,963 218,994 253,1020 287,1046 330,1066 382,1081 433,1095 496,1102 569,1102 705,1102 807,1071 876,1009 945,946 979,856 979,738 L 979,272 C 979,219 986,179 1000,152 1014,125 1041,111 1080,111 1090,111 1100,112 1110,113 1120,114 1130,116 1139,118 L 1139,6 C 1116,1 1094,-3 1072,-6 1049,-9 1025,-10 1000,-10 966,-10 937,-5 913,4 888,13 868,26 853,45 838,63 826,86 818,113 810,140 805,171 803,207 L 797,207 C 778,172 757,141 734,113 711,85 684,61 653,42 622,22 588,7 549,-4 510,-15 465,-20 414,-20 Z M 455,115 C 512,115 563,125 606,146 649,167 684,194 713,226 741,259 762,294 776,332 790,371 797,408 797,443 L 797,531 600,531 C 556,531 514,528 475,522 435,517 400,506 370,489 340,472 316,449 299,418 281,388 272,349 272,300 272,241 288,195 320,163 351,131 396,115 455,115 Z"/>
- <glyph unicode="_" horiz-adv-x="1218" d="M -31,-407 L -31,-277 1162,-277 1162,-407 -31,-407 Z"/>
- <glyph unicode="X" horiz-adv-x="1298" d="M 1112,0 L 689,616 257,0 46,0 582,732 87,1409 298,1409 690,856 1071,1409 1282,1409 800,739 1323,0 1112,0 Z"/>
- <glyph unicode="W" horiz-adv-x="1932" d="M 1511,0 L 1283,0 1039,895 C 1032,920 1024,950 1016,985 1007,1020 1000,1053 993,1084 985,1121 977,1158 969,1196 960,1157 952,1120 944,1083 937,1051 929,1018 921,984 913,950 905,920 898,895 L 652,0 424,0 9,1409 208,1409 461,514 C 472,472 483,430 494,389 504,348 513,311 520,278 529,239 537,203 544,168 554,214 564,259 575,304 580,323 584,342 589,363 594,384 599,404 604,424 609,444 614,463 619,482 624,500 628,517 632,532 L 877,1409 1060,1409 1305,532 C 1309,517 1314,500 1319,482 1324,463 1329,444 1334,425 1339,405 1343,385 1348,364 1353,343 1357,324 1362,305 1373,260 1383,215 1393,168 1394,168 1397,180 1402,203 1407,226 1414,254 1422,289 1430,324 1439,361 1449,402 1458,442 1468,479 1478,514 L 1727,1409 1926,1409 1511,0 Z"/>
- <glyph unicode="V" horiz-adv-x="1377" d="M 782,0 L 584,0 9,1409 210,1409 600,417 C 610,387 620,357 630,328 640,298 649,271 657,248 666,221 675,194 684,168 692,193 701,219 710,246 718,269 727,296 737,325 746,354 757,385 768,417 L 1156,1409 1357,1409 782,0 Z"/>
- <glyph unicode="U" horiz-adv-x="1192" d="M 731,-20 C 654,-20 580,-10 511,11 442,32 381,64 329,108 276,151 235,207 204,274 173,341 158,420 158,512 L 158,1409 349,1409 349,528 C 349,457 359,396 378,347 397,297 423,256 457,225 491,194 531,171 578,157 624,142 675,135 730,135 785,135 836,142 885,157 934,172 976,195 1013,227 1050,259 1079,301 1100,353 1121,404 1131,467 1131,541 L 1131,1409 1321,1409 1321,530 C 1321,436 1306,355 1275,286 1244,217 1201,159 1148,114 1095,69 1032,35 961,13 889,-9 812,-20 731,-20 Z"/>
- <glyph unicode="T" horiz-adv-x="1192" d="M 720,1253 L 720,0 530,0 530,1253 46,1253 46,1409 1204,1409 1204,1253 720,1253 Z"/>
- <glyph unicode="S" horiz-adv-x="1192" d="M 1272,389 C 1272,330 1261,275 1238,225 1215,175 1179,132 1131,96 1083,59 1023,31 950,11 877,-10 790,-20 690,-20 515,-20 378,11 280,72 182,133 120,222 93,338 L 278,375 C 287,338 302,305 321,275 340,245 367,219 400,198 433,176 473,159 522,147 571,135 629,129 697,129 754,129 806,134 853,144 900,153 941,168 975,188 1009,208 1036,234 1055,266 1074,297 1083,335 1083,379 1083,425 1073,462 1052,491 1031,520 1001,543 963,562 925,581 880,596 827,609 774,622 716,635 652,650 613,659 573,668 534,679 494,689 456,701 420,716 383,730 349,747 317,766 285,785 257,809 234,836 211,863 192,894 179,930 166,965 159,1006 159,1053 159,1120 173,1177 200,1225 227,1272 264,1311 312,1342 360,1373 417,1395 482,1409 547,1423 618,1430 694,1430 781,1430 856,1423 918,1410 980,1396 1032,1375 1075,1348 1118,1321 1152,1287 1178,1247 1203,1206 1224,1159 1239,1106 L 1051,1073 C 1042,1107 1028,1137 1011,1164 993,1191 970,1213 941,1231 912,1249 878,1263 837,1272 796,1281 747,1286 692,1286 627,1286 572,1280 528,1269 483,1257 448,1241 421,1221 394,1201 374,1178 363,1151 351,1124 345,1094 345,1063 345,1021 356,987 377,960 398,933 426,910 462,892 498,874 540,859 587,847 634,835 685,823 738,811 781,801 825,791 868,781 911,770 952,758 991,744 1030,729 1067,712 1102,693 1136,674 1166,650 1191,622 1216,594 1236,561 1251,523 1265,485 1272,440 1272,389 Z"/>
- <glyph unicode="R" horiz-adv-x="1244" d="M 1164,0 L 798,585 359,585 359,0 168,0 168,1409 831,1409 C 911,1409 982,1400 1044,1382 1105,1363 1157,1337 1199,1302 1241,1267 1273,1225 1295,1175 1317,1125 1328,1069 1328,1006 1328,961 1322,917 1309,874 1296,831 1275,791 1247,755 1219,719 1183,688 1140,662 1097,636 1045,618 984,607 L 1384,0 1164,0 Z M 1136,1004 C 1136,1047 1129,1084 1114,1115 1099,1146 1078,1173 1050,1194 1022,1215 988,1230 948,1241 908,1251 863,1256 812,1256 L 359,1256 359,736 820,736 C 875,736 922,743 962,757 1002,770 1035,789 1061,813 1086,837 1105,865 1118,898 1130,931 1136,966 1136,1004 Z"/>
- <glyph unicode="P" horiz-adv-x="1112" d="M 1258,985 C 1258,924 1248,867 1228,814 1207,761 1177,715 1137,676 1096,637 1046,606 985,583 924,560 854,549 773,549 L 359,549 359,0 168,0 168,1409 761,1409 C 844,1409 917,1399 979,1379 1041,1358 1093,1330 1134,1293 1175,1256 1206,1211 1227,1159 1248,1106 1258,1048 1258,985 Z M 1066,983 C 1066,1072 1039,1140 984,1187 929,1233 847,1256 738,1256 L 359,1256 359,700 746,700 C 856,700 937,724 989,773 1040,822 1066,892 1066,983 Z"/>
- <glyph unicode="O" horiz-adv-x="1430" d="M 1495,711 C 1495,601 1479,501 1448,411 1416,321 1370,244 1310,180 1250,116 1177,67 1090,32 1003,-3 905,-20 795,-20 679,-20 577,-2 490,35 403,71 330,122 272,187 214,252 170,329 141,418 112,507 97,605 97,711 97,821 112,920 143,1009 174,1098 219,1173 278,1236 337,1298 411,1346 498,1380 585,1413 684,1430 797,1430 909,1430 1009,1413 1096,1379 1183,1345 1256,1297 1315,1234 1374,1171 1418,1096 1449,1007 1480,918 1495,820 1495,711 Z M 1300,711 C 1300,796 1289,873 1268,942 1246,1011 1214,1071 1172,1120 1129,1169 1077,1207 1014,1234 951,1261 879,1274 797,1274 713,1274 639,1261 576,1234 513,1207 460,1169 418,1120 375,1071 344,1011 323,942 302,873 291,796 291,711 291,626 302,549 324,479 345,408 377,348 420,297 462,246 515,206 578,178 641,149 713,135 795,135 883,135 959,149 1023,178 1086,207 1139,247 1180,298 1221,349 1251,409 1271,480 1290,551 1300,628 1300,711 Z"/>
- <glyph unicode="N" horiz-adv-x="1165" d="M 1082,0 L 328,1200 C 329,1167 331,1135 333,1103 334,1076 336,1047 337,1017 338,986 338,959 338,936 L 338,0 168,0 168,1409 390,1409 1152,201 C 1150,234 1148,266 1146,299 1145,327 1143,358 1142,391 1141,424 1140,455 1140,485 L 1140,1409 1312,1409 1312,0 1082,0 Z"/>
- <glyph unicode="M" horiz-adv-x="1377" d="M 1366,0 L 1366,940 C 1366,974 1366,1009 1367,1044 1368,1079 1369,1112 1370,1141 1371,1175 1373,1208 1375,1240 1366,1206 1356,1172 1346,1139 1337,1110 1328,1080 1318,1048 1307,1015 1297,986 1287,960 L 923,0 789,0 420,960 C 416,970 412,982 408,995 403,1008 399,1023 394,1038 389,1053 384,1068 379,1084 374,1099 369,1115 364,1130 353,1165 342,1202 331,1240 332,1203 333,1166 334,1129 335,1098 336,1065 337,1031 338,996 338,966 338,940 L 338,0 168,0 168,1409 419,1409 794,432 C 799,419 804,402 811,381 818,360 824,338 830,316 836,294 842,273 847,254 852,234 855,219 857,208 859,219 863,234 868,254 873,274 880,295 887,317 894,339 900,360 907,381 914,402 920,419 925,432 L 1293,1409 1538,1409 1538,0 1366,0 Z"/>
- <glyph unicode="I" horiz-adv-x="213" d="M 189,0 L 189,1409 380,1409 380,0 189,0 Z"/>
- <glyph unicode="H" horiz-adv-x="1165" d="M 1121,0 L 1121,653 359,653 359,0 168,0 168,1409 359,1409 359,813 1121,813 1121,1409 1312,1409 1312,0 1121,0 Z"/>
- <glyph unicode="F" horiz-adv-x="1006" d="M 359,1253 L 359,729 1145,729 1145,571 359,571 359,0 168,0 168,1409 1169,1409 1169,1253 359,1253 Z"/>
- <glyph unicode="E" horiz-adv-x="1138" d="M 168,0 L 168,1409 1237,1409 1237,1253 359,1253 359,801 1177,801 1177,647 359,647 359,156 1278,156 1278,0 168,0 Z"/>
- <glyph unicode="D" horiz-adv-x="1218" d="M 1381,719 C 1381,602 1363,498 1328,409 1293,319 1244,244 1183,184 1122,123 1049,78 966,47 882,16 792,0 695,0 L 168,0 168,1409 634,1409 C 743,1409 843,1396 935,1369 1026,1342 1105,1300 1171,1244 1237,1187 1289,1116 1326,1029 1363,942 1381,839 1381,719 Z M 1189,719 C 1189,814 1175,896 1148,964 1121,1031 1082,1087 1033,1130 984,1173 925,1205 856,1226 787,1246 712,1256 630,1256 L 359,1256 359,153 673,153 C 747,153 816,165 879,189 942,213 996,249 1042,296 1088,343 1124,402 1150,473 1176,544 1189,626 1189,719 Z"/>
- <glyph unicode="C" horiz-adv-x="1324" d="M 792,1274 C 712,1274 641,1261 580,1234 518,1207 466,1169 425,1120 383,1071 351,1011 330,942 309,873 298,796 298,711 298,626 310,549 333,479 356,408 389,348 432,297 475,246 527,207 590,179 652,151 722,137 800,137 855,137 905,144 950,159 995,173 1035,193 1072,219 1108,245 1140,276 1169,312 1198,347 1223,387 1245,430 L 1401,352 C 1376,299 1344,250 1307,205 1270,160 1226,120 1176,87 1125,54 1068,28 1005,9 941,-10 870,-20 791,-20 677,-20 577,-2 492,35 406,71 334,122 277,187 219,252 176,329 147,418 118,507 104,605 104,711 104,821 119,920 150,1009 180,1098 224,1173 283,1236 341,1298 413,1346 498,1380 583,1413 681,1430 790,1430 940,1430 1065,1401 1166,1342 1267,1283 1341,1196 1388,1081 L 1207,1021 C 1194,1054 1176,1086 1153,1117 1130,1147 1102,1174 1068,1197 1034,1220 994,1239 949,1253 903,1267 851,1274 792,1274 Z"/>
- <glyph unicode="B" horiz-adv-x="1112" d="M 1258,397 C 1258,326 1244,265 1216,215 1188,164 1150,123 1103,92 1056,60 1001,37 938,22 875,7 809,0 740,0 L 168,0 168,1409 680,1409 C 758,1409 828,1403 889,1390 950,1377 1002,1356 1045,1328 1088,1300 1120,1265 1143,1222 1165,1179 1176,1127 1176,1067 1176,1028 1171,991 1160,956 1149,921 1132,890 1110,862 1087,833 1059,809 1026,789 992,768 953,753 908,743 965,736 1015,723 1059,704 1102,685 1139,660 1168,630 1197,600 1220,565 1235,526 1250,486 1258,443 1258,397 Z M 984,1044 C 984,1120 958,1174 906,1207 854,1240 779,1256 680,1256 L 359,1256 359,810 680,810 C 736,810 783,816 822,827 861,838 892,853 916,874 940,894 957,918 968,947 979,976 984,1008 984,1044 Z M 1065,412 C 1065,457 1057,495 1041,526 1024,557 1001,583 970,603 939,623 903,638 860,647 817,656 768,661 715,661 L 359,661 359,153 730,153 C 779,153 824,157 865,165 906,173 941,187 971,207 1000,227 1023,254 1040,287 1057,320 1065,362 1065,412 Z"/>
- <glyph unicode="A" horiz-adv-x="1377" d="M 1167,0 L 1006,412 364,412 202,0 4,0 579,1409 796,1409 1362,0 1167,0 Z M 768,1026 C 757,1053 747,1080 738,1107 728,1134 719,1159 712,1182 705,1204 699,1223 694,1238 689,1253 686,1262 685,1265 684,1262 681,1252 676,1237 671,1222 665,1203 658,1180 650,1157 641,1132 632,1105 622,1078 612,1051 602,1024 L 422,561 949,561 768,1026 Z"/>
- <glyph unicode="2" horiz-adv-x="954" d="M 103,0 L 103,127 C 137,205 179,274 228,334 277,393 328,447 382,496 436,544 490,589 543,630 596,671 643,713 686,754 729,795 763,839 790,884 816,929 829,981 829,1038 829,1078 823,1113 811,1144 799,1174 782,1199 759,1220 736,1241 709,1256 678,1267 646,1277 611,1282 572,1282 536,1282 502,1277 471,1267 439,1257 411,1242 386,1222 361,1202 341,1177 326,1148 310,1118 300,1083 295,1044 L 111,1061 C 117,1112 131,1159 153,1204 175,1249 205,1288 244,1322 283,1355 329,1382 384,1401 438,1420 501,1430 572,1430 642,1430 704,1422 759,1405 814,1388 860,1364 898,1331 935,1298 964,1258 984,1210 1004,1162 1014,1107 1014,1044 1014,997 1006,952 989,909 972,866 949,826 921,787 892,748 859,711 822,675 785,639 746,604 705,570 664,535 623,501 582,468 541,434 502,400 466,366 429,332 397,298 368,263 339,228 317,191 301,153 L 1036,153 1036,0 103,0 Z"/>
- <glyph unicode="1" horiz-adv-x="927" d="M 156,0 L 156,153 515,153 515,1237 197,1010 197,1180 530,1409 696,1409 696,153 1039,153 1039,0 156,0 Z"/>
- <glyph unicode="." horiz-adv-x="213" d="M 187,0 L 187,219 382,219 382,0 187,0 Z"/>
- <glyph unicode="," horiz-adv-x="239" d="M 385,219 L 385,51 C 385,16 384,-16 381,-46 378,-74 373,-101 366,-127 359,-151 351,-175 342,-197 332,-219 320,-241 307,-262 L 184,-262 C 214,-219 237,-175 254,-131 270,-87 278,-43 278,0 L 190,0 190,219 385,219 Z"/>
- <glyph unicode=")" horiz-adv-x="557" d="M 555,528 C 555,435 548,346 534,262 520,177 498,96 468,18 438,-60 400,-136 353,-209 306,-282 251,-354 186,-424 L 12,-424 C 75,-354 129,-282 175,-209 220,-136 258,-60 287,19 316,98 338,179 353,264 367,349 374,437 374,530 374,623 367,711 353,796 338,881 316,962 287,1041 258,1119 220,1195 175,1269 129,1342 75,1414 12,1484 L 186,1484 C 251,1414 306,1342 353,1269 400,1196 438,1120 468,1042 498,964 520,883 534,798 548,713 555,625 555,532 L 555,528 Z"/>
- <glyph unicode="(" horiz-adv-x="583" d="M 127,532 C 127,625 134,713 148,798 162,883 184,964 214,1042 244,1120 282,1196 329,1269 376,1342 431,1414 496,1484 L 670,1484 C 607,1414 553,1342 508,1269 462,1195 424,1119 395,1041 366,962 344,881 330,796 315,711 308,623 308,530 308,437 315,349 330,264 344,179 366,98 395,19 424,-60 462,-136 508,-209 553,-282 607,-354 670,-424 L 496,-424 C 431,-354 376,-282 329,-209 282,-136 244,-60 214,18 184,96 162,177 148,262 134,346 127,435 127,528 L 127,532 Z"/>
- <glyph unicode=" " horiz-adv-x="556"/>
- </font>
- </defs>
- <defs class="TextShapeIndex">
- <g ooo:slide="id1" ooo:id-list="id3 id4 id5 id6 id7 id8 id9 id10 id11 id12 id13 id14 id15 id16 id17 id18 id19 id20 id21 id22 id23 id24 id25 id26 id27 id28 id29 id30 id31 id32 id33 id34 id35 id36 id37 id38 id39 id40 id41 id42 id43 id44 id45 id46 id47 id48 id49 id50 id51 id52 id53 id54 id55 id56 id57 id58"/>
- </defs>
- <defs class="EmbeddedBulletChars">
- <g id="bullet-char-template(57356)" transform="scale(0.00048828125,-0.00048828125)">
- <path d="M 580,1141 L 1163,571 580,0 -4,571 580,1141 Z"/>
- </g>
- <g id="bullet-char-template(57354)" transform="scale(0.00048828125,-0.00048828125)">
- <path d="M 8,1128 L 1137,1128 1137,0 8,0 8,1128 Z"/>
- </g>
- <g id="bullet-char-template(10146)" transform="scale(0.00048828125,-0.00048828125)">
- <path d="M 174,0 L 602,739 174,1481 1456,739 174,0 Z M 1358,739 L 309,1346 659,739 1358,739 Z"/>
- </g>
- <g id="bullet-char-template(10132)" transform="scale(0.00048828125,-0.00048828125)">
- <path d="M 2015,739 L 1276,0 717,0 1260,543 174,543 174,936 1260,936 717,1481 1274,1481 2015,739 Z"/>
- </g>
- <g id="bullet-char-template(10007)" transform="scale(0.00048828125,-0.00048828125)">
- <path d="M 0,-2 C -7,14 -16,27 -25,37 L 356,567 C 262,823 215,952 215,954 215,979 228,992 255,992 264,992 276,990 289,987 310,991 331,999 354,1012 L 381,999 492,748 772,1049 836,1024 860,1049 C 881,1039 901,1025 922,1006 886,937 835,863 770,784 769,783 710,716 594,584 L 774,223 C 774,196 753,168 711,139 L 727,119 C 717,90 699,76 672,76 641,76 570,178 457,381 L 164,-76 C 142,-110 111,-127 72,-127 30,-127 9,-110 8,-76 1,-67 -2,-52 -2,-32 -2,-23 -1,-13 0,-2 Z"/>
- </g>
- <g id="bullet-char-template(10004)" transform="scale(0.00048828125,-0.00048828125)">
- <path d="M 285,-33 C 182,-33 111,30 74,156 52,228 41,333 41,471 41,549 55,616 82,672 116,743 169,778 240,778 293,778 328,747 346,684 L 369,508 C 377,444 397,411 428,410 L 1163,1116 C 1174,1127 1196,1133 1229,1133 1271,1133 1292,1118 1292,1087 L 1292,965 C 1292,929 1282,901 1262,881 L 442,47 C 390,-6 338,-33 285,-33 Z"/>
- </g>
- <g id="bullet-char-template(9679)" transform="scale(0.00048828125,-0.00048828125)">
- <path d="M 813,0 C 632,0 489,54 383,161 276,268 223,411 223,592 223,773 276,916 383,1023 489,1130 632,1184 813,1184 992,1184 1136,1130 1245,1023 1353,916 1407,772 1407,592 1407,412 1353,268 1245,161 1136,54 992,0 813,0 Z"/>
- </g>
- <g id="bullet-char-template(8226)" transform="scale(0.00048828125,-0.00048828125)">
- <path d="M 346,457 C 273,457 209,483 155,535 101,586 74,649 74,723 74,796 101,859 155,911 209,963 273,989 346,989 419,989 480,963 531,910 582,859 608,796 608,723 608,648 583,586 532,535 482,483 420,457 346,457 Z"/>
- </g>
- <g id="bullet-char-template(8211)" transform="scale(0.00048828125,-0.00048828125)">
- <path d="M -4,459 L 1135,459 1135,606 -4,606 -4,459 Z"/>
- </g>
- </defs>
- <defs class="TextEmbeddedBitmaps"/>
- <g>
- <g id="id2" class="Master_Slide">
- <g id="bg-id2" class="Background">
- <path fill="rgb(255,255,255)" stroke="none" d="M 10503,29692 L 0,29692 0,0 21005,0 21005,29692 10503,29692 Z"/>
- </g>
- <g id="bo-id2" class="BackgroundObjects"/>
- </g>
- </g>
- <g class="SlideGroup">
- <g>
- <g id="id1" class="Slide" clip-path="url(#presentation_clip_path)">
- <g class="Page">
- <g class="com.sun.star.drawing.CustomShape">
- <g id="id3">
- <rect class="BoundingBox" stroke="none" fill="none" x="4766" y="1239" width="2822" height="894"/>
- <path fill="rgb(128,128,128)" stroke="none" d="M 4967,1440 L 7586,1440 7586,2131 4967,2131 4967,1440 4967,1440 Z M 4967,1440 L 4967,1440 Z M 7586,2131 L 7586,2131 Z"/>
- <path fill="none" stroke="rgb(128,128,128)" d="M 4967,1440 L 7586,1440 7586,2131 4967,2131 4967,1440 4967,1440 Z"/>
- <path fill="none" stroke="rgb(128,128,128)" d="M 4967,1440 L 4967,1440 Z"/>
- <path fill="none" stroke="rgb(128,128,128)" d="M 7586,2131 L 7586,2131 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="5995" y="1906"><tspan fill="rgb(128,128,128)" stroke="none">API</tspan></tspan></tspan></text>
- <path fill="rgb(255,255,255)" stroke="none" d="M 4767,1240 L 7386,1240 7386,1931 4767,1931 4767,1240 4767,1240 Z M 4767,1240 L 4767,1240 Z M 7386,1931 L 7386,1931 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 4767,1240 L 7386,1240 7386,1931 4767,1931 4767,1240 4767,1240 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 4767,1240 L 4767,1240 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 7386,1931 L 7386,1931 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="5795" y="1706"><tspan fill="rgb(0,0,0)" stroke="none">API</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id4">
- <rect class="BoundingBox" stroke="none" fill="none" x="6059" y="1929" width="45" height="24727"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6102,1930 L 6102,2082"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6102,2133 L 6101,2285"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6101,2336 L 6101,2488"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6101,2539 L 6101,2691"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6101,2742 L 6100,2894"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6100,2945 L 6100,3097"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6100,3148 L 6100,3300"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6100,3351 L 6099,3503"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6099,3554 L 6099,3706"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6099,3757 L 6099,3909"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6099,3960 L 6098,4112"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6098,4163 L 6098,4315"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6098,4366 L 6098,4518"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6098,4569 L 6097,4721"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6097,4772 L 6097,4924"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6097,4975 L 6097,5127"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6096,5178 L 6096,5330"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6096,5381 L 6096,5533"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6096,5584 L 6096,5736"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6095,5787 L 6095,5939"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6095,5990 L 6095,6142"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6095,6193 L 6095,6345"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6094,6396 L 6094,6548"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6094,6599 L 6094,6751"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6094,6802 L 6093,6954"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6093,7005 L 6093,7157"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6093,7208 L 6093,7360"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6093,7411 L 6092,7563"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6092,7614 L 6092,7766"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6092,7817 L 6092,7969"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6092,8020 L 6091,8172"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6091,8223 L 6091,8375"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6091,8426 L 6091,8578"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6091,8629 L 6090,8781"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6090,8832 L 6090,8984"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6090,9035 L 6090,9187"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6090,9238 L 6089,9390"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6089,9441 L 6089,9593"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6089,9644 L 6089,9796"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6089,9847 L 6088,9999"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6088,10050 L 6088,10202"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6088,10253 L 6088,10405"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6088,10456 L 6087,10608"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6087,10659 L 6087,10811"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6087,10862 L 6087,11014"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6086,11065 L 6086,11217"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6086,11268 L 6086,11420"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6086,11471 L 6086,11623"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6085,11674 L 6085,11826"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6085,11877 L 6085,12029"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6085,12080 L 6084,12232"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6084,12283 L 6084,12435"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6084,12486 L 6084,12638"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6084,12689 L 6083,12841"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6083,12892 L 6083,13044"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6083,13095 L 6083,13247"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6083,13298 L 6082,13450"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6082,13501 L 6082,13653"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6082,13704 L 6082,13856"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6082,13907 L 6081,14059"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6081,14110 L 6081,14262"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6081,14313 L 6081,14465"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6081,14516 L 6080,14668"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6080,14719 L 6080,14871"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6080,14922 L 6080,15074"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6080,15125 L 6079,15277"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6079,15328 L 6079,15480"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6079,15531 L 6079,15683"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6079,15734 L 6078,15886"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6078,15937 L 6078,16089"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6078,16140 L 6078,16292"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6078,16343 L 6077,16495"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6077,16546 L 6077,16698"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6077,16749 L 6077,16901"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6076,16952 L 6076,17104"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6076,17155 L 6076,17307"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6076,17358 L 6076,17510"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6075,17561 L 6075,17713"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6075,17764 L 6075,17916"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6075,17967 L 6074,18119"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6074,18170 L 6074,18322"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6074,18373 L 6074,18525"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6074,18576 L 6073,18728"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6073,18779 L 6073,18931"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6073,18982 L 6073,19134"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6073,19185 L 6072,19337"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6072,19388 L 6072,19540"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6072,19591 L 6072,19743"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6072,19794 L 6071,19946"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6071,19997 L 6071,20149"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6071,20200 L 6071,20352"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6071,20403 L 6070,20555"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6070,20606 L 6070,20758"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6070,20809 L 6070,20961"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6070,21012 L 6069,21164"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6069,21215 L 6069,21367"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6069,21418 L 6069,21570"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6069,21621 L 6068,21773"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6068,21824 L 6068,21976"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6068,22027 L 6068,22179"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6068,22230 L 6067,22382"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6067,22433 L 6067,22585"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6067,22636 L 6067,22788"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6066,22839 L 6066,22991"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6066,23042 L 6066,23194"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6066,23245 L 6066,23397"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6065,23448 L 6065,23600"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6065,23651 L 6065,23803"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6065,23854 L 6064,24006"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6064,24057 L 6064,24209"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6064,24260 L 6064,24412"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6064,24463 L 6063,24615"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6063,24666 L 6063,24818"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6063,24869 L 6063,25021"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6063,25072 L 6062,25224"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6062,25275 L 6062,25427"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6062,25478 L 6062,25630"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6062,25681 L 6061,25833"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6061,25884 L 6061,26036"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6061,26087 L 6061,26239"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6061,26290 L 6060,26442"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6060,26493 L 6060,26645"/>
- </g>
- </g>
- <g class="com.sun.star.drawing.CustomShape">
- <g id="id5">
- <rect class="BoundingBox" stroke="none" fill="none" x="7821" y="1245" width="2825" height="893"/>
- <path fill="rgb(128,128,128)" stroke="none" d="M 8022,1446 L 10644,1446 10644,2136 8022,2136 8022,1446 8022,1446 Z M 8022,1446 L 8022,1446 Z M 10644,2136 L 10644,2136 Z"/>
- <path fill="none" stroke="rgb(128,128,128)" d="M 8022,1446 L 10644,1446 10644,2136 8022,2136 8022,1446 8022,1446 Z"/>
- <path fill="none" stroke="rgb(128,128,128)" d="M 8022,1446 L 8022,1446 Z"/>
- <path fill="none" stroke="rgb(128,128,128)" d="M 10644,2136 L 10644,2136 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="8522" y="1912"><tspan fill="rgb(128,128,128)" stroke="none">Conductor</tspan></tspan></tspan></text>
- <path fill="rgb(255,255,255)" stroke="none" d="M 7822,1246 L 10444,1246 10444,1936 7822,1936 7822,1246 7822,1246 Z M 7822,1246 L 7822,1246 Z M 10444,1936 L 10444,1936 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 7822,1246 L 10444,1246 10444,1936 7822,1936 7822,1246 7822,1246 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 7822,1246 L 7822,1246 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 10444,1936 L 10444,1936 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="8322" y="1712"><tspan fill="rgb(0,0,0)" stroke="none">Conductor</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id6">
- <rect class="BoundingBox" stroke="none" fill="none" x="9117" y="1947" width="44" height="24709"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9159,1948 L 9159,2100"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9159,2151 L 9158,2303"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9158,2354 L 9158,2506"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9158,2557 L 9158,2709"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9158,2760 L 9157,2912"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9157,2963 L 9157,3115"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9157,3166 L 9157,3318"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9157,3369 L 9156,3520"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9156,3571 L 9156,3723"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9156,3774 L 9156,3926"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9156,3977 L 9155,4129"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9155,4180 L 9155,4332"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9155,4383 L 9155,4535"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9155,4586 L 9154,4738"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9154,4789 L 9154,4941"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9154,4992 L 9154,5144"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9154,5195 L 9153,5347"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9153,5398 L 9153,5550"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9153,5601 L 9153,5753"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9153,5804 L 9152,5956"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9152,6007 L 9152,6159"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9152,6210 L 9152,6362"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9152,6413 L 9151,6565"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9151,6616 L 9151,6768"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9151,6819 L 9151,6971"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9151,7022 L 9150,7174"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9150,7225 L 9150,7377"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9150,7428 L 9150,7580"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9150,7631 L 9149,7783"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9149,7834 L 9149,7986"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9149,8037 L 9149,8189"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9149,8240 L 9148,8392"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9148,8443 L 9148,8595"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9148,8646 L 9148,8798"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9148,8849 L 9147,9001"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9147,9052 L 9147,9204"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9147,9255 L 9147,9407"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9147,9458 L 9146,9610"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9146,9661 L 9146,9813"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9146,9864 L 9146,10016"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9146,10067 L 9145,10219"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9145,10270 L 9145,10422"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9145,10473 L 9145,10625"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9145,10676 L 9144,10828"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9144,10879 L 9144,11031"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9144,11082 L 9144,11234"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9144,11285 L 9143,11437"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9143,11488 L 9143,11640"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9143,11691 L 9143,11843"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9142,11894 L 9142,12046"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9142,12097 L 9142,12249"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9142,12300 L 9142,12452"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9141,12503 L 9141,12655"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9141,12706 L 9141,12858"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9141,12909 L 9141,13061"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9140,13112 L 9140,13264"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9140,13315 L 9140,13467"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9140,13518 L 9140,13670"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9139,13721 L 9139,13873"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9139,13924 L 9139,14076"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9139,14127 L 9139,14279"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9138,14330 L 9138,14482"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9138,14533 L 9138,14685"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9138,14736 L 9138,14888"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9137,14939 L 9137,15091"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9137,15142 L 9137,15294"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9137,15345 L 9137,15497"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9136,15548 L 9136,15700"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9136,15751 L 9136,15903"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9136,15954 L 9136,16106"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9135,16157 L 9135,16309"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9135,16360 L 9135,16512"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9135,16563 L 9134,16715"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9134,16766 L 9134,16918"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9134,16969 L 9134,17121"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9134,17172 L 9133,17324"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9133,17375 L 9133,17527"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9133,17578 L 9133,17730"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9133,17781 L 9132,17933"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9132,17984 L 9132,18136"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9132,18187 L 9132,18339"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9132,18390 L 9131,18542"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9131,18593 L 9131,18745"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9131,18796 L 9131,18948"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9131,18999 L 9130,19151"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9130,19202 L 9130,19354"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9130,19405 L 9130,19557"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9130,19608 L 9129,19760"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9129,19811 L 9129,19963"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9129,20014 L 9129,20166"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9129,20217 L 9128,20369"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9128,20420 L 9128,20572"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9128,20623 L 9128,20775"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9128,20826 L 9127,20978"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9127,21029 L 9127,21181"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9127,21232 L 9127,21384"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9127,21435 L 9126,21587"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9126,21638 L 9126,21790"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9126,21841 L 9126,21993"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9126,22044 L 9125,22196"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9125,22247 L 9125,22399"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9125,22450 L 9125,22602"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9125,22653 L 9124,22805"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9124,22856 L 9124,23008"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9124,23059 L 9124,23211"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9124,23262 L 9123,23414"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9123,23465 L 9123,23617"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9123,23668 L 9123,23820"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9123,23871 L 9122,24023"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9122,24074 L 9122,24226"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9122,24277 L 9122,24429"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9122,24480 L 9121,24632"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9121,24683 L 9121,24835"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9121,24886 L 9121,25038"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9121,25089 L 9120,25241"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9120,25292 L 9120,25444"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9120,25495 L 9120,25647"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9120,25698 L 9119,25850"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9119,25901 L 9119,26053"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9119,26104 L 9119,26256"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9119,26307 L 9118,26459"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9118,26510 L 9118,26654"/>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id7">
- <rect class="BoundingBox" stroke="none" fill="none" x="6069" y="9968" width="3050" height="455"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 6070,10322 L 8831,10322"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 9118,10322 L 8818,10222 8818,10422 9118,10322 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="6273" y="10174"><tspan fill="rgb(0,0,0)" stroke="none">do node deploy</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.CustomShape">
- <g id="id8">
- <rect class="BoundingBox" stroke="none" fill="none" x="1249" y="1239" width="2824" height="894"/>
- <path fill="rgb(128,128,128)" stroke="none" d="M 1450,1440 L 4071,1440 4071,2131 1450,2131 1450,1440 1450,1440 Z M 1450,1440 L 1450,1440 Z M 4071,2131 L 4071,2131 Z"/>
- <path fill="none" stroke="rgb(128,128,128)" d="M 1450,1440 L 4071,1440 4071,2131 1450,2131 1450,1440 1450,1440 Z"/>
- <path fill="none" stroke="rgb(128,128,128)" d="M 1450,1440 L 1450,1440 Z"/>
- <path fill="none" stroke="rgb(128,128,128)" d="M 4071,2131 L 4071,2131 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="2388" y="1906"><tspan fill="rgb(128,128,128)" stroke="none">User</tspan></tspan></tspan></text>
- <path fill="rgb(255,255,255)" stroke="none" d="M 1250,1240 L 3871,1240 3871,1931 1250,1931 1250,1240 1250,1240 Z M 1250,1240 L 1250,1240 Z M 3871,1931 L 3871,1931 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 1250,1240 L 3871,1240 3871,1931 1250,1931 1250,1240 1250,1240 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 1250,1240 L 1250,1240 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 3871,1931 L 3871,1931 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="2188" y="1706"><tspan fill="rgb(0,0,0)" stroke="none">User</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id9">
- <rect class="BoundingBox" stroke="none" fill="none" x="2474" y="2037" width="72" height="24619"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2544,2038 L 2544,2190"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2543,2241 L 2543,2393"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2543,2444 L 2542,2596"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2542,2647 L 2542,2799"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2542,2850 L 2541,3002"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2541,3053 L 2541,3205"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2541,3256 L 2540,3408"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2540,3459 L 2540,3611"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2539,3662 L 2539,3814"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2539,3865 L 2538,4017"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2538,4068 L 2538,4220"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2538,4271 L 2537,4423"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2537,4474 L 2537,4626"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2537,4677 L 2536,4829"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2536,4880 L 2536,5032"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2535,5083 L 2535,5235"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2535,5286 L 2534,5438"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2534,5489 L 2534,5641"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2534,5692 L 2533,5844"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2533,5895 L 2533,6047"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2533,6098 L 2532,6250"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2532,6301 L 2532,6453"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2531,6504 L 2531,6656"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2531,6707 L 2530,6859"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2530,6910 L 2530,7062"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2530,7113 L 2529,7265"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2529,7316 L 2529,7468"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2529,7519 L 2528,7671"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2528,7722 L 2528,7874"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2527,7925 L 2527,8077"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2527,8128 L 2527,8280"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2526,8331 L 2526,8483"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2526,8534 L 2525,8686"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2525,8737 L 2525,8889"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2525,8940 L 2524,9092"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2524,9143 L 2524,9295"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2524,9346 L 2523,9498"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2523,9549 L 2523,9701"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2522,9752 L 2522,9904"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2522,9955 L 2521,10107"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2521,10158 L 2521,10310"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2521,10361 L 2520,10513"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2520,10564 L 2520,10716"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2520,10767 L 2519,10919"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2519,10970 L 2519,11122"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2518,11173 L 2518,11325"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2518,11376 L 2517,11528"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2517,11579 L 2517,11731"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2517,11782 L 2516,11934"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2516,11985 L 2516,12137"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2516,12188 L 2515,12340"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2515,12391 L 2515,12543"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2514,12594 L 2514,12746"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2514,12797 L 2513,12949"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2513,13000 L 2513,13152"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2513,13203 L 2512,13355"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2512,13406 L 2512,13558"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2512,13609 L 2511,13761"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2511,13812 L 2511,13964"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2510,14015 L 2510,14167"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2510,14218 L 2509,14370"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2509,14421 L 2509,14573"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2509,14624 L 2508,14776"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2508,14827 L 2508,14979"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2508,15030 L 2507,15182"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2507,15233 L 2507,15385"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2506,15436 L 2506,15588"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2506,15639 L 2505,15791"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2505,15842 L 2505,15994"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2505,16045 L 2504,16197"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2504,16248 L 2504,16400"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2504,16451 L 2503,16603"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2503,16654 L 2503,16806"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2502,16857 L 2502,17009"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2502,17060 L 2501,17212"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2501,17263 L 2501,17415"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2501,17466 L 2500,17618"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2500,17669 L 2500,17821"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2500,17872 L 2499,18024"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2499,18075 L 2499,18227"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2498,18278 L 2498,18430"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2498,18481 L 2497,18633"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2497,18684 L 2497,18836"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2497,18887 L 2496,19039"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2496,19090 L 2496,19242"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2496,19293 L 2495,19445"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2495,19496 L 2495,19648"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2494,19699 L 2494,19851"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2494,19902 L 2494,20054"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2493,20105 L 2493,20257"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2493,20308 L 2492,20460"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2492,20511 L 2492,20663"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2492,20714 L 2491,20866"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2491,20917 L 2491,21069"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2491,21120 L 2490,21272"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2490,21323 L 2490,21475"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2489,21526 L 2489,21678"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2489,21729 L 2488,21881"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2488,21932 L 2488,22084"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2488,22135 L 2487,22287"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2487,22338 L 2487,22490"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2487,22541 L 2486,22693"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2486,22744 L 2486,22896"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2485,22947 L 2485,23099"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2485,23150 L 2484,23302"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2484,23353 L 2484,23505"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2484,23556 L 2483,23708"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2483,23759 L 2483,23911"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2483,23962 L 2482,24114"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2482,24165 L 2482,24317"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2481,24368 L 2481,24520"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2481,24571 L 2480,24723"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2480,24774 L 2480,24926"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2480,24977 L 2479,25129"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2479,25180 L 2479,25332"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2479,25383 L 2478,25535"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2478,25586 L 2478,25738"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2477,25789 L 2477,25941"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2477,25992 L 2476,26144"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2476,26195 L 2476,26347"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2476,26398 L 2475,26550"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2475,26601 L 2475,26654"/>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id10">
- <rect class="BoundingBox" stroke="none" fill="none" x="2581" y="2244" width="3436" height="455"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2582,2597 L 5729,2597"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 6016,2597 L 5716,2497 5716,2697 6016,2597 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="2684" y="2449"><tspan fill="rgb(0,0,0)" stroke="none">Create ibmc driver node</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id11">
- <rect class="BoundingBox" stroke="none" fill="none" x="2626" y="2999" width="3436" height="1370"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2627,4267 L 5774,4267"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 6061,4267 L 5761,4167 5761,4367 6061,4267 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="2729" y="3204"><tspan fill="rgb(0,0,0)" stroke="none">Set driver_info </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="2729" y="3522"><tspan fill="rgb(0,0,0)" stroke="none">(ibmc_address, </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="2729" y="3840"><tspan fill="rgb(0,0,0)" stroke="none">ibmc_username, </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="2729" y="4158"><tspan fill="rgb(0,0,0)" stroke="none">ibmc_password, etc)</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id12">
- <rect class="BoundingBox" stroke="none" fill="none" x="2581" y="4714" width="3436" height="1116"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2582,5728 L 5729,5728"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 6016,5728 L 5716,5628 5716,5828 6016,5728 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="2684" y="4919"><tspan fill="rgb(0,0,0)" stroke="none">Set instance_info</tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="2684" y="5237"><tspan fill="rgb(0,0,0)" stroke="none">(image_source, </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="2684" y="5555"><tspan fill="rgb(0,0,0)" stroke="none">root_gb, etc.)</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id13">
- <rect class="BoundingBox" stroke="none" fill="none" x="2581" y="6125" width="3436" height="1167"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2582,7191 L 5729,7191"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 6016,7191 L 5716,7091 5716,7291 6016,7191 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="2684" y="6331"><tspan fill="rgb(0,0,0)" stroke="none">Validate power, </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="2684" y="6649"><tspan fill="rgb(0,0,0)" stroke="none">management and </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="2684" y="6967"><tspan fill="rgb(0,0,0)" stroke="none">vendor interfaces</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id14">
- <rect class="BoundingBox" stroke="none" fill="none" x="2559" y="7591" width="3436" height="862"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2560,8351 L 5707,8351"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 5994,8351 L 5694,8251 5694,8451 5994,8351 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="2662" y="7796"><tspan fill="rgb(0,0,0)" stroke="none">Create bare metal </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="2662" y="8114"><tspan fill="rgb(0,0,0)" stroke="none">node network port</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id15">
- <rect class="BoundingBox" stroke="none" fill="none" x="2514" y="8368" width="3436" height="1116"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2515,9382 L 5662,9382"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 5949,9382 L 5649,9282 5649,9482 5949,9382 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="2617" y="8573"><tspan fill="rgb(0,0,0)" stroke="none">Set provision_state, </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="2617" y="8891"><tspan fill="rgb(0,0,0)" stroke="none">optionally pass </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="2617" y="9209"><tspan fill="rgb(0,0,0)" stroke="none">configdrive</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.CustomShape">
- <g id="id16">
- <rect class="BoundingBox" stroke="none" fill="none" x="10779" y="1245" width="2824" height="893"/>
- <path fill="rgb(128,128,128)" stroke="none" d="M 10980,1446 L 13601,1446 13601,2136 10980,2136 10980,1446 10980,1446 Z M 10980,1446 L 10980,1446 Z M 13601,2136 L 13601,2136 Z"/>
- <path fill="none" stroke="rgb(128,128,128)" d="M 10980,1446 L 13601,1446 13601,2136 10980,2136 10980,1446 10980,1446 Z"/>
- <path fill="none" stroke="rgb(128,128,128)" d="M 10980,1446 L 10980,1446 Z"/>
- <path fill="none" stroke="rgb(128,128,128)" d="M 13601,2136 L 13601,2136 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="11793" y="1912"><tspan fill="rgb(128,128,128)" stroke="none">DHCP</tspan></tspan></tspan></text>
- <path fill="rgb(255,255,255)" stroke="none" d="M 10780,1246 L 13401,1246 13401,1936 10780,1936 10780,1246 10780,1246 Z M 10780,1246 L 10780,1246 Z M 13401,1936 L 13401,1936 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 10780,1246 L 13401,1246 13401,1936 10780,1936 10780,1246 10780,1246 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 10780,1246 L 10780,1246 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 13401,1936 L 13401,1936 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="11593" y="1712"><tspan fill="rgb(0,0,0)" stroke="none">DHCP</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id17">
- <rect class="BoundingBox" stroke="none" fill="none" x="12074" y="1947" width="44" height="24709"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12116,1948 L 12116,2100"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12116,2151 L 12115,2303"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12115,2354 L 12115,2506"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12115,2557 L 12115,2709"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12115,2760 L 12114,2912"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12114,2963 L 12114,3115"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12114,3166 L 12114,3318"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12114,3369 L 12113,3520"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12113,3571 L 12113,3723"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12113,3774 L 12113,3926"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12113,3977 L 12112,4129"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12112,4180 L 12112,4332"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12112,4383 L 12112,4535"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12112,4586 L 12111,4738"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12111,4789 L 12111,4941"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12111,4992 L 12111,5144"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12111,5195 L 12110,5347"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12110,5398 L 12110,5550"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12110,5601 L 12110,5753"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12110,5804 L 12109,5956"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12109,6007 L 12109,6159"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12109,6210 L 12109,6362"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12109,6413 L 12108,6565"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12108,6616 L 12108,6768"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12108,6819 L 12108,6971"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12108,7022 L 12107,7174"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12107,7225 L 12107,7377"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12107,7428 L 12107,7580"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12107,7631 L 12106,7783"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12106,7834 L 12106,7986"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12106,8037 L 12106,8189"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12106,8240 L 12105,8392"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12105,8443 L 12105,8595"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12105,8646 L 12105,8798"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12105,8849 L 12104,9001"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12104,9052 L 12104,9204"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12104,9255 L 12104,9407"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12104,9458 L 12103,9610"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12103,9661 L 12103,9813"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12103,9864 L 12103,10016"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12103,10067 L 12102,10219"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12102,10270 L 12102,10422"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12102,10473 L 12102,10625"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12102,10676 L 12101,10828"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12101,10879 L 12101,11031"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12101,11082 L 12101,11234"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12101,11285 L 12100,11437"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12100,11488 L 12100,11640"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12100,11691 L 12100,11843"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12099,11894 L 12099,12046"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12099,12097 L 12099,12249"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12099,12300 L 12099,12452"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12098,12503 L 12098,12655"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12098,12706 L 12098,12858"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12098,12909 L 12098,13061"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12097,13112 L 12097,13264"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12097,13315 L 12097,13467"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12097,13518 L 12097,13670"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12096,13721 L 12096,13873"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12096,13924 L 12096,14076"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12096,14127 L 12096,14279"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12095,14330 L 12095,14482"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12095,14533 L 12095,14685"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12095,14736 L 12095,14888"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12094,14939 L 12094,15091"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12094,15142 L 12094,15294"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12094,15345 L 12094,15497"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12093,15548 L 12093,15700"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12093,15751 L 12093,15903"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12093,15954 L 12093,16106"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12092,16157 L 12092,16309"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12092,16360 L 12092,16512"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12092,16563 L 12091,16715"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12091,16766 L 12091,16918"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12091,16969 L 12091,17121"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12091,17172 L 12090,17324"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12090,17375 L 12090,17527"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12090,17578 L 12090,17730"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12090,17781 L 12089,17933"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12089,17984 L 12089,18136"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12089,18187 L 12089,18339"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12089,18390 L 12088,18542"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12088,18593 L 12088,18745"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12088,18796 L 12088,18948"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12088,18999 L 12087,19151"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12087,19202 L 12087,19354"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12087,19405 L 12087,19557"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12087,19608 L 12086,19760"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12086,19811 L 12086,19963"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12086,20014 L 12086,20166"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12086,20217 L 12085,20369"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12085,20420 L 12085,20572"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12085,20623 L 12085,20775"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12085,20826 L 12084,20978"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12084,21029 L 12084,21181"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12084,21232 L 12084,21384"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12084,21435 L 12083,21587"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12083,21638 L 12083,21790"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12083,21841 L 12083,21993"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12083,22044 L 12082,22196"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12082,22247 L 12082,22399"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12082,22450 L 12082,22602"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12082,22653 L 12081,22805"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12081,22856 L 12081,23008"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12081,23059 L 12081,23211"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12081,23262 L 12080,23414"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12080,23465 L 12080,23617"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12080,23668 L 12080,23820"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12080,23871 L 12079,24023"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12079,24074 L 12079,24226"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12079,24277 L 12079,24429"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12079,24480 L 12078,24632"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12078,24683 L 12078,24835"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12078,24886 L 12078,25038"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12078,25089 L 12077,25241"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12077,25292 L 12077,25444"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12077,25495 L 12077,25647"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12077,25698 L 12076,25850"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12076,25901 L 12076,26053"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12076,26104 L 12076,26256"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12076,26307 L 12075,26459"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12075,26510 L 12075,26654"/>
- </g>
- </g>
- <g class="com.sun.star.drawing.CustomShape">
- <g id="id18">
- <rect class="BoundingBox" stroke="none" fill="none" x="13682" y="1245" width="2825" height="893"/>
- <path fill="rgb(128,128,128)" stroke="none" d="M 13883,1446 L 16505,1446 16505,2136 13883,2136 13883,1446 13883,1446 Z M 13883,1446 L 13883,1446 Z M 16505,2136 L 16505,2136 Z"/>
- <path fill="none" stroke="rgb(128,128,128)" d="M 13883,1446 L 16505,1446 16505,2136 13883,2136 13883,1446 13883,1446 Z"/>
- <path fill="none" stroke="rgb(128,128,128)" d="M 13883,1446 L 13883,1446 Z"/>
- <path fill="none" stroke="rgb(128,128,128)" d="M 16505,2136 L 16505,2136 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="14753" y="1912"><tspan fill="rgb(128,128,128)" stroke="none">TFTP</tspan></tspan></tspan></text>
- <path fill="rgb(255,255,255)" stroke="none" d="M 13683,1246 L 16305,1246 16305,1936 13683,1936 13683,1246 13683,1246 Z M 13683,1246 L 13683,1246 Z M 16305,1936 L 16305,1936 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 13683,1246 L 16305,1246 16305,1936 13683,1936 13683,1246 13683,1246 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 13683,1246 L 13683,1246 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 16305,1936 L 16305,1936 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="14553" y="1712"><tspan fill="rgb(0,0,0)" stroke="none">TFTP</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id19">
- <rect class="BoundingBox" stroke="none" fill="none" x="14978" y="1947" width="44" height="24709"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15020,1948 L 15020,2100"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15020,2151 L 15019,2303"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15019,2354 L 15019,2506"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15019,2557 L 15019,2709"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15019,2760 L 15018,2912"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15018,2963 L 15018,3115"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15018,3166 L 15018,3318"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15018,3369 L 15017,3520"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15017,3571 L 15017,3723"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15017,3774 L 15017,3926"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15017,3977 L 15016,4129"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15016,4180 L 15016,4332"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15016,4383 L 15016,4535"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15016,4586 L 15015,4738"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15015,4789 L 15015,4941"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15015,4992 L 15015,5144"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15015,5195 L 15014,5347"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15014,5398 L 15014,5550"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15014,5601 L 15014,5753"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15014,5804 L 15013,5956"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15013,6007 L 15013,6159"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15013,6210 L 15013,6362"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15013,6413 L 15012,6565"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15012,6616 L 15012,6768"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15012,6819 L 15012,6971"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15012,7022 L 15011,7174"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15011,7225 L 15011,7377"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15011,7428 L 15011,7580"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15011,7631 L 15010,7783"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15010,7834 L 15010,7986"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15010,8037 L 15010,8189"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15010,8240 L 15009,8392"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15009,8443 L 15009,8595"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15009,8646 L 15009,8798"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15009,8849 L 15008,9001"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15008,9052 L 15008,9204"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15008,9255 L 15008,9407"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15008,9458 L 15007,9610"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15007,9661 L 15007,9813"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15007,9864 L 15007,10016"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15007,10067 L 15006,10219"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15006,10270 L 15006,10422"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15006,10473 L 15006,10625"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15006,10676 L 15005,10828"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15005,10879 L 15005,11031"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15005,11082 L 15005,11234"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15005,11285 L 15004,11437"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15004,11488 L 15004,11640"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15004,11691 L 15004,11843"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15003,11894 L 15003,12046"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15003,12097 L 15003,12249"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15003,12300 L 15003,12452"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15002,12503 L 15002,12655"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15002,12706 L 15002,12858"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15002,12909 L 15002,13061"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15001,13112 L 15001,13264"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15001,13315 L 15001,13467"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15001,13518 L 15001,13670"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15000,13721 L 15000,13873"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15000,13924 L 15000,14076"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 15000,14127 L 15000,14279"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14999,14330 L 14999,14482"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14999,14533 L 14999,14685"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14999,14736 L 14999,14888"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14998,14939 L 14998,15091"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14998,15142 L 14998,15294"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14998,15345 L 14998,15497"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14997,15548 L 14997,15700"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14997,15751 L 14997,15903"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14997,15954 L 14997,16106"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14996,16157 L 14996,16309"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14996,16360 L 14996,16512"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14996,16563 L 14995,16715"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14995,16766 L 14995,16918"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14995,16969 L 14995,17121"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14995,17172 L 14994,17324"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14994,17375 L 14994,17527"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14994,17578 L 14994,17730"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14994,17781 L 14993,17933"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14993,17984 L 14993,18136"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14993,18187 L 14993,18339"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14993,18390 L 14992,18542"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14992,18593 L 14992,18745"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14992,18796 L 14992,18948"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14992,18999 L 14991,19151"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14991,19202 L 14991,19354"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14991,19405 L 14991,19557"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14991,19608 L 14990,19760"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14990,19811 L 14990,19963"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14990,20014 L 14990,20166"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14990,20217 L 14989,20369"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14989,20420 L 14989,20572"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14989,20623 L 14989,20775"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14989,20826 L 14988,20978"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14988,21029 L 14988,21181"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14988,21232 L 14988,21384"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14988,21435 L 14987,21587"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14987,21638 L 14987,21790"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14987,21841 L 14987,21993"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14987,22044 L 14986,22196"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14986,22247 L 14986,22399"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14986,22450 L 14986,22602"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14986,22653 L 14985,22805"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14985,22856 L 14985,23008"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14985,23059 L 14985,23211"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14985,23262 L 14984,23414"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14984,23465 L 14984,23617"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14984,23668 L 14984,23820"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14984,23871 L 14983,24023"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14983,24074 L 14983,24226"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14983,24277 L 14983,24429"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14983,24480 L 14982,24632"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14982,24683 L 14982,24835"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14982,24886 L 14982,25038"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14982,25089 L 14981,25241"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14981,25292 L 14981,25444"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14981,25495 L 14981,25647"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14981,25698 L 14980,25850"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14980,25901 L 14980,26053"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14980,26104 L 14980,26256"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14980,26307 L 14979,26459"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14979,26510 L 14979,26654"/>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id20">
- <rect class="BoundingBox" stroke="none" fill="none" x="9273" y="11583" width="1413" height="3"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9274,11584 L 10684,11584"/>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id21">
- <rect class="BoundingBox" stroke="none" fill="none" x="10683" y="11583" width="3" height="434"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 10684,11584 L 10684,12015"/>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id22">
- <rect class="BoundingBox" stroke="none" fill="none" x="9146" y="11865" width="1563" height="302"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 10707,12015 L 9576,12015"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 9146,12015 L 9596,12165 9596,11865 9146,12015 Z"/>
- </g>
- </g>
- <g class="com.sun.star.drawing.TextShape">
- <g id="id23">
- <rect class="BoundingBox" stroke="none" fill="none" x="9146" y="10292" width="3358" height="1354"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="9248" y="11007"><tspan fill="rgb(0,0,0)" stroke="none">Validate power, </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="9248" y="11325"><tspan fill="rgb(0,0,0)" stroke="none">management and </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="9248" y="11643"><tspan fill="rgb(0,0,0)" stroke="none">vendor interfaces</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.CustomShape">
- <g id="id24">
- <rect class="BoundingBox" stroke="none" fill="none" x="16854" y="1238" width="2824" height="893"/>
- <path fill="rgb(128,128,128)" stroke="none" d="M 17055,1439 L 19676,1439 19676,2129 17055,2129 17055,1439 17055,1439 Z M 17055,1439 L 17055,1439 Z M 19676,2129 L 19676,2129 Z"/>
- <path fill="none" stroke="rgb(128,128,128)" d="M 17055,1439 L 19676,1439 19676,2129 17055,2129 17055,1439 17055,1439 Z"/>
- <path fill="none" stroke="rgb(128,128,128)" d="M 17055,1439 L 17055,1439 Z"/>
- <path fill="none" stroke="rgb(128,128,128)" d="M 19676,2129 L 19676,2129 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="17946" y="1905"><tspan fill="rgb(128,128,128)" stroke="none">Node</tspan></tspan></tspan></text>
- <path fill="rgb(255,255,255)" stroke="none" d="M 16855,1239 L 19476,1239 19476,1929 16855,1929 16855,1239 16855,1239 Z M 16855,1239 L 16855,1239 Z M 19476,1929 L 19476,1929 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 16855,1239 L 19476,1239 19476,1929 16855,1929 16855,1239 16855,1239 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 16855,1239 L 16855,1239 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 19476,1929 L 19476,1929 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="353px" font-weight="400"><tspan class="TextPosition" x="17746" y="1705"><tspan fill="rgb(0,0,0)" stroke="none">Node</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id25">
- <rect class="BoundingBox" stroke="none" fill="none" x="18149" y="1938" width="44" height="24710"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18191,1939 L 18191,2091"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18191,2142 L 18190,2294"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18190,2345 L 18190,2497"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18190,2548 L 18190,2700"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18190,2751 L 18189,2903"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18189,2954 L 18189,3106"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18189,3157 L 18189,3309"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18189,3360 L 18188,3512"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18188,3563 L 18188,3715"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18188,3766 L 18188,3918"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18188,3969 L 18187,4121"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18187,4172 L 18187,4324"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18187,4375 L 18187,4527"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18187,4578 L 18186,4730"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18186,4781 L 18186,4933"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18186,4984 L 18186,5136"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18186,5187 L 18185,5339"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18185,5390 L 18185,5542"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18185,5593 L 18185,5745"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18185,5796 L 18184,5948"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18184,5999 L 18184,6151"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18184,6202 L 18184,6354"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18184,6405 L 18183,6557"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18183,6608 L 18183,6760"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18183,6811 L 18183,6963"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18183,7014 L 18182,7166"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18182,7217 L 18182,7369"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18182,7420 L 18182,7572"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18182,7623 L 18181,7775"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18181,7826 L 18181,7978"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18181,8029 L 18181,8181"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18181,8232 L 18180,8384"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18180,8435 L 18180,8587"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18180,8638 L 18180,8790"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18180,8841 L 18179,8993"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18179,9044 L 18179,9196"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18179,9247 L 18179,9399"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18179,9450 L 18178,9602"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18178,9653 L 18178,9805"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18178,9856 L 18178,10008"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18178,10059 L 18177,10211"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18177,10262 L 18177,10414"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18177,10465 L 18177,10617"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18177,10668 L 18176,10820"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18176,10871 L 18176,11023"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18176,11074 L 18176,11226"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18176,11277 L 18175,11429"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18175,11480 L 18175,11632"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18175,11683 L 18175,11835"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18174,11886 L 18174,12038"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18174,12089 L 18174,12241"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18174,12292 L 18174,12444"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18173,12495 L 18173,12647"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18173,12698 L 18173,12850"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18173,12901 L 18173,13053"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18172,13104 L 18172,13256"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18172,13307 L 18172,13459"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18172,13510 L 18172,13662"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18171,13713 L 18171,13865"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18171,13916 L 18171,14068"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18171,14119 L 18171,14271"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18170,14322 L 18170,14474"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18170,14525 L 18170,14677"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18170,14728 L 18170,14880"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18169,14931 L 18169,15083"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18169,15134 L 18169,15286"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18169,15337 L 18169,15489"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18168,15540 L 18168,15692"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18168,15743 L 18168,15895"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18168,15946 L 18168,16098"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18167,16149 L 18167,16301"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18167,16352 L 18167,16504"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18167,16555 L 18166,16707"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18166,16758 L 18166,16910"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18166,16961 L 18166,17113"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18166,17164 L 18165,17316"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18165,17367 L 18165,17519"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18165,17570 L 18165,17722"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18165,17773 L 18164,17925"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18164,17976 L 18164,18128"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18164,18179 L 18164,18331"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18164,18382 L 18163,18534"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18163,18585 L 18163,18737"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18163,18788 L 18163,18940"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18163,18991 L 18162,19143"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18162,19194 L 18162,19346"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18162,19397 L 18162,19549"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18162,19600 L 18161,19752"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18161,19803 L 18161,19955"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18161,20006 L 18161,20158"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18161,20209 L 18160,20361"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18160,20412 L 18160,20564"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18160,20615 L 18160,20767"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18160,20818 L 18159,20970"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18159,21021 L 18159,21173"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18159,21224 L 18159,21376"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18159,21427 L 18158,21579"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18158,21630 L 18158,21782"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18158,21833 L 18158,21985"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18158,22036 L 18157,22188"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18157,22239 L 18157,22391"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18157,22442 L 18157,22594"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18157,22645 L 18156,22797"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18156,22848 L 18156,23000"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18156,23051 L 18156,23203"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18156,23254 L 18155,23406"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18155,23457 L 18155,23609"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18155,23660 L 18155,23812"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18155,23863 L 18154,24015"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18154,24066 L 18154,24218"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18154,24269 L 18154,24421"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18154,24472 L 18153,24624"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18153,24675 L 18153,24827"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18153,24878 L 18153,25030"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18153,25081 L 18152,25233"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18152,25284 L 18152,25436"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18152,25487 L 18152,25639"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18152,25690 L 18151,25842"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18151,25893 L 18151,26045"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18151,26096 L 18151,26248"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18151,26299 L 18150,26451"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18150,26502 L 18150,26646"/>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id26">
- <rect class="BoundingBox" stroke="none" fill="none" x="9208" y="14004" width="8897" height="857"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9209,14710 L 17674,14710"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 18104,14710 L 17654,14560 17654,14860 18104,14710 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="283px" font-weight="400"><tspan class="TextPosition" x="9260" y="14210"><tspan fill="rgb(0,0,0)" stroke="none">Set PXE boot device</tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="283px" font-weight="400"><tspan class="TextPosition" x="9260" y="14532"><tspan fill="rgb(0,0,0)" stroke="none">through iBMC</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id27">
- <rect class="BoundingBox" stroke="none" fill="none" x="9208" y="15218" width="8897" height="505"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9209,15571 L 17674,15571"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 18104,15571 L 17654,15421 17654,15721 18104,15571 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="9209" y="15423"><tspan fill="rgb(0,0,0)" stroke="none">REBOOT through iBMC</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id28">
- <rect class="BoundingBox" stroke="none" fill="none" x="18103" y="19731" width="1540" height="302"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 19641,19882 L 18533,19882"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 18103,19882 L 18553,20032 18553,19732 18103,19882 Z"/>
- </g>
- </g>
- <g class="com.sun.star.drawing.TextShape">
- <g id="id29">
- <rect class="BoundingBox" stroke="none" fill="none" x="9285" y="11800" width="3358" height="1461"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="9285" y="12566"><tspan fill="rgb(0,0,0)" stroke="none">Prepare PXE</tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="9285" y="12884"><tspan fill="rgb(0,0,0)" stroke="none">environment for</tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="9285" y="13202"><tspan fill="rgb(0,0,0)" stroke="none">deployment</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id30">
- <rect class="BoundingBox" stroke="none" fill="none" x="18259" y="18802" width="1445" height="650"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 18260,19450 L 19670,19450"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="18402" y="18997"><tspan fill="rgb(0,0,0)" stroke="none">Run agent </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="18402" y="19315"><tspan fill="rgb(0,0,0)" stroke="none">ramdisk</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id31">
- <rect class="BoundingBox" stroke="none" fill="none" x="19669" y="19449" width="3" height="434"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 19670,19450 L 19670,19881"/>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id32">
- <rect class="BoundingBox" stroke="none" fill="none" x="12174" y="16295" width="5932" height="455"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12461,16649 L 18104,16649"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 12174,16649 L 12474,16749 12474,16549 12174,16649 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="12174" y="16501"><tspan fill="rgb(0,0,0)" stroke="none">Send PXE DHCP request</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id33">
- <rect class="BoundingBox" stroke="none" fill="none" x="12173" y="16942" width="6088" height="505"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12174,17296 L 17830,17296"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 18260,17296 L 17810,17146 17810,17446 18260,17296 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="12174" y="17148"><tspan fill="rgb(0,0,0)" stroke="none">Offer IP to node</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id34">
- <rect class="BoundingBox" stroke="none" fill="none" x="14982" y="17822" width="3279" height="810"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14983,18481 L 17830,18481"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 18260,18481 L 17810,18331 17810,18631 18260,18481 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="15135" y="18028"><tspan fill="rgb(0,0,0)" stroke="none">Send PXE image </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="15135" y="18346"><tspan fill="rgb(0,0,0)" stroke="none">and agent image </tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id35">
- <rect class="BoundingBox" stroke="none" fill="none" x="9203" y="13482" width="1540" height="302"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 10741,13632 L 9633,13632"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 9203,13632 L 9653,13782 9653,13482 9203,13632 Z"/>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id36">
- <rect class="BoundingBox" stroke="none" fill="none" x="10769" y="13199" width="3" height="434"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 10770,13200 L 10770,13631"/>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id37">
- <rect class="BoundingBox" stroke="none" fill="none" x="9208" y="13199" width="1564" height="3"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 10770,13200 L 9209,13200"/>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id38">
- <rect class="BoundingBox" stroke="none" fill="none" x="9208" y="20384" width="8897" height="404"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9209,20636 L 17674,20636"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 18104,20636 L 17654,20486 17654,20786 18104,20636 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="9260" y="20589"><tspan fill="rgb(0,0,0)" stroke="none">Send IPA a command to expose disks via iSCSI</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id39">
- <rect class="BoundingBox" stroke="none" fill="none" x="9208" y="20849" width="8897" height="404"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9209,21101 L 17674,21101"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 18104,21101 L 17654,20951 17654,21251 18104,21101 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="9260" y="21054"><tspan fill="rgb(0,0,0)" stroke="none">iSCSI attach</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id40">
- <rect class="BoundingBox" stroke="none" fill="none" x="9208" y="21314" width="8897" height="404"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9209,21567 L 17674,21567"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 18104,21567 L 17654,21417 17654,21717 18104,21567 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="9260" y="21520"><tspan fill="rgb(0,0,0)" stroke="none">Copies user image and configdrive, if presend</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id41">
- <rect class="BoundingBox" stroke="none" fill="none" x="9208" y="21789" width="8897" height="404"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9209,22042 L 17674,22042"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 18104,22042 L 17654,21892 17654,22192 18104,22042 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="9260" y="21995"><tspan fill="rgb(0,0,0)" stroke="none">iSCSI detach</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id42">
- <rect class="BoundingBox" stroke="none" fill="none" x="9208" y="22397" width="8897" height="404"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9209,22649 L 17674,22649"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 18104,22649 L 17654,22499 17654,22799 18104,22649 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="9260" y="22602"><tspan fill="rgb(0,0,0)" stroke="none">Install boot loader if requested</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id43">
- <rect class="BoundingBox" stroke="none" fill="none" x="9208" y="23004" width="8897" height="404"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9209,23257 L 17674,23257"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 18104,23257 L 17654,23107 17654,23407 18104,23257 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="9260" y="23210"><tspan fill="rgb(0,0,0)" stroke="none">Set boot device either to PXE or to disk</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id44">
- <rect class="BoundingBox" stroke="none" fill="none" x="9208" y="23612" width="8897" height="404"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9209,23864 L 17674,23864"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 18104,23864 L 17654,23714 17654,24014 18104,23864 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="9260" y="23817"><tspan fill="rgb(0,0,0)" stroke="none">Collect ramdisk logs</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id45">
- <rect class="BoundingBox" stroke="none" fill="none" x="9208" y="24227" width="8897" height="396"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9209,24472 L 17674,24472"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 18104,24472 L 17654,24322 17654,24622 18104,24472 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="9260" y="24425"><tspan fill="rgb(0,0,0)" stroke="none">POWER OFF</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id46">
- <rect class="BoundingBox" stroke="none" fill="none" x="9208" y="24835" width="8897" height="396"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9209,25079 L 17674,25079"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 18104,25079 L 17654,24929 17654,25229 18104,25079 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="9260" y="25032"><tspan fill="rgb(0,0,0)" stroke="none">POWER ON</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id47">
- <rect class="BoundingBox" stroke="none" fill="none" x="9056" y="25334" width="2500" height="610"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 9057,25942 L 11554,25942"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="9413" y="25540"><tspan fill="rgb(0,0,0)" stroke="none">Mark node as </tspan></tspan></tspan><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="9413" y="25858"><tspan fill="rgb(0,0,0)" stroke="none">ACTIVE</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id48">
- <rect class="BoundingBox" stroke="none" fill="none" x="11553" y="25941" width="3" height="596"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 11554,25942 L 11554,26535"/>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id49">
- <rect class="BoundingBox" stroke="none" fill="none" x="9057" y="26385" width="2499" height="302"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 11554,26535 L 9487,26535"/>
- <path fill="rgb(0,0,0)" stroke="none" d="M 9057,26535 L 9507,26685 9507,26385 9057,26535 Z"/>
- </g>
- </g>
- <g class="com.sun.star.drawing.CustomShape">
- <g id="id50">
- <rect class="BoundingBox" stroke="none" fill="none" x="11920" y="13952" width="385" height="385"/>
- <path fill="rgb(255,255,255)" stroke="none" d="M 12111,13953 C 12219,13953 12302,14035 12302,14143 12302,14251 12219,14334 12111,14334 12003,14334 11921,14251 11921,14143 11921,14035 12003,13953 12111,13953 Z M 11921,13953 L 11921,13953 Z M 12303,14335 L 12303,14335 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12111,13953 C 12219,13953 12302,14035 12302,14143 12302,14251 12219,14334 12111,14334 12003,14334 11921,14251 11921,14143 11921,14035 12003,13953 12111,13953 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 11921,13953 L 11921,13953 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12303,14335 L 12303,14335 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="12033" y="14268"><tspan fill="rgb(0,0,0)" stroke="none">1</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.CustomShape">
- <g id="id51">
- <rect class="BoundingBox" stroke="none" fill="none" x="12320" y="15052" width="385" height="385"/>
- <path fill="rgb(255,255,255)" stroke="none" d="M 12511,15053 C 12619,15053 12702,15135 12702,15243 12702,15351 12619,15434 12511,15434 12403,15434 12321,15351 12321,15243 12321,15135 12403,15053 12511,15053 Z M 12321,15053 L 12321,15053 Z M 12703,15435 L 12703,15435 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12511,15053 C 12619,15053 12702,15135 12702,15243 12702,15351 12619,15434 12511,15434 12403,15434 12321,15351 12321,15243 12321,15135 12403,15053 12511,15053 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12321,15053 L 12321,15053 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 12703,15435 L 12703,15435 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="12433" y="15368"><tspan fill="rgb(0,0,0)" stroke="none">2</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.CustomShape">
- <g id="id52">
- <rect class="BoundingBox" stroke="none" fill="none" x="14320" y="22852" width="385" height="385"/>
- <path fill="rgb(255,255,255)" stroke="none" d="M 14511,22853 C 14619,22853 14702,22935 14702,23043 14702,23151 14619,23234 14511,23234 14403,23234 14321,23151 14321,23043 14321,22935 14403,22853 14511,22853 Z M 14321,22853 L 14321,22853 Z M 14703,23235 L 14703,23235 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14511,22853 C 14619,22853 14702,22935 14702,23043 14702,23151 14619,23234 14511,23234 14403,23234 14321,23151 14321,23043 14321,22935 14403,22853 14511,22853 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14321,22853 L 14321,22853 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 14703,23235 L 14703,23235 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="14433" y="23168"><tspan fill="rgb(0,0,0)" stroke="none">1</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.CustomShape">
- <g id="id53">
- <rect class="BoundingBox" stroke="none" fill="none" x="11120" y="24052" width="385" height="385"/>
- <path fill="rgb(255,255,255)" stroke="none" d="M 11311,24053 C 11419,24053 11502,24135 11502,24243 11502,24351 11419,24434 11311,24434 11203,24434 11121,24351 11121,24243 11121,24135 11203,24053 11311,24053 Z M 11121,24053 L 11121,24053 Z M 11503,24435 L 11503,24435 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 11311,24053 C 11419,24053 11502,24135 11502,24243 11502,24351 11419,24434 11311,24434 11203,24434 11121,24351 11121,24243 11121,24135 11203,24053 11311,24053 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 11121,24053 L 11121,24053 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 11503,24435 L 11503,24435 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="11233" y="24368"><tspan fill="rgb(0,0,0)" stroke="none">2</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.CustomShape">
- <g id="id54">
- <rect class="BoundingBox" stroke="none" fill="none" x="10920" y="24652" width="385" height="385"/>
- <path fill="rgb(255,255,255)" stroke="none" d="M 11111,24653 C 11219,24653 11302,24735 11302,24843 11302,24951 11219,25034 11111,25034 11003,25034 10921,24951 10921,24843 10921,24735 11003,24653 11111,24653 Z M 10921,24653 L 10921,24653 Z M 11303,25035 L 11303,25035 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 11111,24653 C 11219,24653 11302,24735 11302,24843 11302,24951 11219,25034 11111,25034 11003,25034 10921,24951 10921,24843 10921,24735 11003,24653 11111,24653 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 10921,24653 L 10921,24653 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 11303,25035 L 11303,25035 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="11033" y="24968"><tspan fill="rgb(0,0,0)" stroke="none">2</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.CustomShape">
- <g id="id55">
- <rect class="BoundingBox" stroke="none" fill="none" x="2320" y="27952" width="385" height="385"/>
- <path fill="rgb(255,255,255)" stroke="none" d="M 2511,27953 C 2619,27953 2702,28035 2702,28143 2702,28251 2619,28334 2511,28334 2403,28334 2321,28251 2321,28143 2321,28035 2403,27953 2511,27953 Z M 2321,27953 L 2321,27953 Z M 2703,28335 L 2703,28335 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2511,27953 C 2619,27953 2702,28035 2702,28143 2702,28251 2619,28334 2511,28334 2403,28334 2321,28251 2321,28143 2321,28035 2403,27953 2511,27953 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2321,27953 L 2321,27953 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2703,28335 L 2703,28335 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="2433" y="28268"><tspan fill="rgb(0,0,0)" stroke="none">2</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.CustomShape">
- <g id="id56">
- <rect class="BoundingBox" stroke="none" fill="none" x="2320" y="27320" width="385" height="385"/>
- <path fill="rgb(255,255,255)" stroke="none" d="M 2511,27321 C 2619,27321 2702,27403 2702,27511 2702,27619 2619,27702 2511,27702 2403,27702 2321,27619 2321,27511 2321,27403 2403,27321 2511,27321 Z M 2321,27321 L 2321,27321 Z M 2703,27703 L 2703,27703 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2511,27321 C 2619,27321 2702,27403 2702,27511 2702,27619 2619,27702 2511,27702 2403,27702 2321,27619 2321,27511 2321,27403 2403,27321 2511,27321 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2321,27321 L 2321,27321 Z"/>
- <path fill="none" stroke="rgb(0,0,0)" d="M 2703,27703 L 2703,27703 Z"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="2433" y="27636"><tspan fill="rgb(0,0,0)" stroke="none">1</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id57">
- <rect class="BoundingBox" stroke="none" fill="none" x="2769" y="27408" width="3588" height="305"/>
- <path fill="none" stroke="rgb(255,255,255)" d="M 2778,27711 L 6334,27711"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="2778" y="27613"><tspan fill="rgb(0,0,0)" stroke="none">IBMC management interface</tspan></tspan></tspan></text>
- </g>
- </g>
- <g class="com.sun.star.drawing.LineShape">
- <g id="id58">
- <rect class="BoundingBox" stroke="none" fill="none" x="2776" y="28061" width="3567" height="305"/>
- <path fill="none" stroke="rgb(255,255,255)" d="M 2785,28364 L 6341,28364"/>
- <text class="TextShape"><tspan class="TextParagraph" font-family="Liberation Sans, sans-serif" font-size="282px" font-weight="400"><tspan class="TextPosition" x="2785" y="28266"><tspan fill="rgb(0,0,0)" stroke="none">IBMC power interface</tspan></tspan></tspan></text>
- </g>
- </g>
- </g>
- </g>
- </g>
- </g>
-</svg> \ No newline at end of file
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 7cc671c86..601d6b16c 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -40,7 +40,6 @@ Upgrade Guide
:maxdepth: 2
admin/upgrade-guide
- admin/upgrade-to-hardware-types
User Guide
==========
diff --git a/doc/source/install/configure-iscsi.rst b/doc/source/install/configure-iscsi.rst
deleted file mode 100644
index ce90376f5..000000000
--- a/doc/source/install/configure-iscsi.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-Configuring iSCSI-based drivers
--------------------------------
-
-Ensure that the ``qemu-img`` and ``iscsiadm`` tools are installed on the
-**ironic-conductor** host(s).
diff --git a/doc/source/install/configure-tenant-networks.rst b/doc/source/install/configure-tenant-networks.rst
index 37656483b..6fca4cd50 100644
--- a/doc/source/install/configure-tenant-networks.rst
+++ b/doc/source/install/configure-tenant-networks.rst
@@ -93,10 +93,8 @@ provisioning will happen in a multi-tenant environment (which means using the
* TFTP
* egress port used for the Bare Metal service (6385 by default)
* ingress port used for ironic-python-agent (9999 by default)
- * if using :ref:`iscsi-deploy`, the ingress port used for iSCSI
- (3260 by default)
* if using :ref:`direct-deploy`, the egress port used for the Object
- Storage service (typically 80 or 443)
+ Storage service or the local HTTP server (typically 80 or 443)
* if using iPXE, the egress port used for the HTTP server running
on the ironic-conductor nodes (typically 80).
diff --git a/doc/source/install/enabling-drivers.rst b/doc/source/install/enabling-drivers.rst
index 344b37131..81c1b9178 100644
--- a/doc/source/install/enabling-drivers.rst
+++ b/doc/source/install/enabling-drivers.rst
@@ -78,7 +78,7 @@ console
deploy
defines how the image gets transferred to the target disk. See
:doc:`/admin/interfaces/deploy` for an explanation of the difference
- between supported deploy interfaces ``direct`` and ``iscsi``.
+ between supported deploy interfaces.
The deploy interfaces can be enabled as follows:
@@ -86,13 +86,10 @@ deploy
[DEFAULT]
enabled_hardware_types = ipmi,redfish
- enabled_deploy_interfaces = iscsi,direct
+ enabled_deploy_interfaces = direct,ramdisk
- Additionally,
-
- * the ``iscsi`` deploy interface requires :doc:`configure-iscsi`
-
- * the ``direct`` deploy interface requires the Object Storage service
+ .. note::
+ The ``direct`` deploy interface requires the Object Storage service
or an HTTP service
inspect
implements fetching hardware information from nodes. Can be implemented
@@ -186,7 +183,7 @@ IPMI and Redfish, with a few additional features:
enabled_hardware_types = ipmi,redfish
enabled_boot_interfaces = pxe
enabled_console_interfaces = ipmitool-socat,no-console
- enabled_deploy_interfaces = iscsi,direct
+ enabled_deploy_interfaces = direct
enabled_inspect_interfaces = inspector
enabled_management_interfaces = ipmitool,redfish
enabled_network_interfaces = flat,neutron
@@ -222,7 +219,7 @@ respectively:
[DEFAULT]
enabled_hardware_types = redfish
- enabled_deploy_interfaces = iscsi
+ enabled_deploy_interfaces = ansible
enabled_power_interfaces = redfish
enabled_management_interfaces = redfish
@@ -241,13 +238,13 @@ respectively:
[DEFAULT]
enabled_hardware_types = redfish
- enabled_deploy_interfaces = iscsi
+ enabled_deploy_interfaces = ansible
enabled_power_interfaces = redfish
enabled_management_interfaces = redfish
This is because the ``redfish`` hardware type will have different enabled
*deploy* interfaces on these conductors. It would have been fine, if the second
-conductor had ``enabled_deploy_interfaces = direct`` instead of ``iscsi``.
+conductor had ``enabled_deploy_interfaces = direct`` instead of ``ansible``.
This situation is not detected by the Bare Metal service, but it can cause
inconsistent behavior in the API, when node functionality will depend on
diff --git a/doc/source/install/enrollment.rst b/doc/source/install/enrollment.rst
index ce20f5aad..f52ca08ab 100644
--- a/doc/source/install/enrollment.rst
+++ b/doc/source/install/enrollment.rst
@@ -572,7 +572,7 @@ interfaces for a hardware type (for your deployment):
+-------------------------------+----------------+
| default_boot_interface | pxe |
| default_console_interface | no-console |
- | default_deploy_interface | iscsi |
+ | default_deploy_interface | direct |
| default_inspect_interface | no-inspect |
| default_management_interface | ipmitool |
| default_network_interface | flat |
@@ -581,7 +581,7 @@ interfaces for a hardware type (for your deployment):
| default_vendor_interface | no-vendor |
| enabled_boot_interfaces | pxe |
| enabled_console_interfaces | no-console |
- | enabled_deploy_interfaces | iscsi, direct |
+ | enabled_deploy_interfaces | direct |
| enabled_inspect_interfaces | no-inspect |
| enabled_management_interfaces | ipmitool |
| enabled_network_interfaces | flat, noop |
@@ -627,10 +627,10 @@ Consider the following configuration (shortened for simplicity):
[DEFAULT]
enabled_hardware_types = ipmi,redfish
enabled_console_interfaces = no-console,ipmitool-shellinabox
- enabled_deploy_interfaces = iscsi,direct
+ enabled_deploy_interfaces = direct
enabled_management_interfaces = ipmitool,redfish
enabled_power_interfaces = ipmitool,redfish
- default_deploy_interface = direct
+ default_deploy_interface = ansible
A new node is created with the ``ipmi`` driver and no interfaces specified:
@@ -654,7 +654,7 @@ Then the defaults for the interfaces that will be used by the node in this
example are calculated as follows:
deploy
- An explicit value of ``direct`` is provided for
+ An explicit value of ``ansible`` is provided for
``default_deploy_interface``, so it is used.
power
No default is configured. The ``ipmi`` hardware type supports only
diff --git a/doc/source/install/refarch/common.rst b/doc/source/install/refarch/common.rst
index f4fdac2b8..ec2a0dbbb 100644
--- a/doc/source/install/refarch/common.rst
+++ b/doc/source/install/refarch/common.rst
@@ -99,18 +99,6 @@ implementation is available for the hardware, it is recommended using it
for better scalability and security. Otherwise, it is recommended to use iPXE,
when it is supported by target hardware.
-Deploy interface
-~~~~~~~~~~~~~~~~
-
-There are two deploy interfaces in-tree, ``iscsi`` and ``direct``. See
-:doc:`../../admin/interfaces/deploy` for explanation of the difference.
-With the ``iscsi`` deploy method, most of the deployment operations happen on
-the conductor. If the Object Storage service (swift) or RadosGW is present in
-the environment, it is recommended to use the ``direct`` deploy method for
-better scalability and reliability.
-
-.. TODO(dtantsur): say something about the ansible deploy, when it's in
-
Hardware specifications
~~~~~~~~~~~~~~~~~~~~~~~
@@ -328,11 +316,6 @@ the space requirements are different:
``image_download_source`` can also be provided in the node's
``driver_info`` or ``instance_info``. See :ref:`image_download_source`.
-* The ``iscsi`` deploy method always requires caching of the whole instance
- image locally during the deployment. The image has to be converted to the raw
- format, which may increase the required amount of disk space, as well as the
- CPU load.
-
* When network boot is used, the instance image kernel and ramdisk are cached
locally while the instance is active.
diff --git a/doc/source/install/setup-drivers.rst b/doc/source/install/setup-drivers.rst
index 41abd1f49..8e69b52d6 100644
--- a/doc/source/install/setup-drivers.rst
+++ b/doc/source/install/setup-drivers.rst
@@ -7,4 +7,3 @@ Set up the drivers for the Bare Metal service
enabling-drivers
configure-pxe
configure-ipmi
- configure-iscsi
diff --git a/doc/source/user/index.rst b/doc/source/user/index.rst
index c6884558c..41eba082a 100644
--- a/doc/source/user/index.rst
+++ b/doc/source/user/index.rst
@@ -260,7 +260,7 @@ options.
.. _direct-deploy-example:
-Example 1: PXE Boot and Direct Deploy Process
+Example: PXE Boot and Direct Deploy Process
---------------------------------------------
This process is how :ref:`direct-deploy` works.
@@ -318,63 +318,5 @@ This process is how :ref:`direct-deploy` works.
(From a `talk`_ and `slides`_)
-.. _iscsi-deploy-example:
-
-Example 2: PXE Boot and iSCSI Deploy Process
---------------------------------------------
-
-This process is how the currently deprecated :ref:`iscsi-deploy` works.
-
-.. seqdiag::
- :scale: 75
-
- diagram {
- Nova; API; Conductor; Neutron; HTTPStore; "TFTP/HTTPd"; Node;
- activation = none;
- span_height = 1;
- edge_length = 250;
- default_note_color = white;
- default_fontsize = 14;
-
- Nova -> API [label = "Set instance_info\n(image_source,\nroot_gb, etc.)"];
- Nova -> API [label = "Validate power and deploy\ninterfaces"];
- Nova -> API [label = "Plug VIFs to the node"];
- Nova -> API [label = "Set provision_state,\noptionally pass configdrive"];
- API -> Conductor [label = "do_node_deploy()"];
- Conductor -> Conductor [label = "Validate power and deploy interfaces"];
- Conductor -> HTTPStore [label = "Store configdrive if configdrive_use_swift \noption is set"];
- Conductor -> Node [label = "POWER OFF"];
- Conductor -> Neutron [label = "Attach provisioning network to port(s)"];
- Conductor -> Neutron [label = "Update DHCP boot options"];
- Conductor -> Conductor [label = "Prepare PXE\nenvironment for\ndeployment"];
- Conductor -> Node [label = "Set PXE boot device \nthrough the BMC"];
- Conductor -> Conductor [label = "Cache deploy\nkernel, ramdisk,\ninstance images"];
- Conductor -> Node [label = "REBOOT"];
- Node -> Neutron [label = "DHCP request"];
- Neutron -> Node [label = "next-server = Conductor"];
- Node -> Node [label = "Runs agent\nramdisk"];
- Node -> API [label = "lookup()"];
- API -> Node [label = "Pass UUID"];
- Node -> API [label = "Heartbeat (UUID)"];
- API -> Conductor [label = "Heartbeat"];
- Conductor -> Node [label = "Send IPA a command to expose disks via iSCSI"];
- Conductor -> Node [label = "iSCSI attach"];
- Conductor -> Node [label = "Copies user image and configdrive, if present"];
- Conductor -> Node [label = "iSCSI detach"];
- Conductor -> Conductor [label = "Delete instance\nimage from cache"];
- Conductor -> Node [label = "Install boot loader, if requested"];
- Conductor -> Neutron [label = "Update DHCP boot options"];
- Conductor -> Conductor [label = "Prepare PXE\nenvironment for\ninstance image"];
- Conductor -> Node [label = "Set boot device either to PXE or to disk"];
- Conductor -> Node [label = "Collect ramdisk logs"];
- Conductor -> Node [label = "POWER OFF"];
- Conductor -> Neutron [label = "Detach provisioning network\nfrom port(s)"];
- Conductor -> Neutron [label = "Bind tenant port"];
- Conductor -> Node [label = "POWER ON"];
- Conductor -> Conductor [label = "Mark node as\nACTIVE"];
- }
-
-(From a `talk`_ and `slides`_)
-
.. _talk: https://www.openstack.org/summit/vancouver-2015/summit-videos/presentation/isn-and-039t-it-ironic-the-bare-metal-cloud
.. _slides: http://www.slideshare.net/devananda1/isnt-it-ironic-managing-a-bare-metal-cloud-osl-tes-2015
diff --git a/etc/ironic/rootwrap.d/ironic-utils.filters b/etc/ironic/rootwrap.d/ironic-utils.filters
index ad7de6f0d..e1ac730d8 100644
--- a/etc/ironic/rootwrap.d/ironic-utils.filters
+++ b/etc/ironic/rootwrap.d/ironic-utils.filters
@@ -2,9 +2,6 @@
# This file should be owned by (and only-writable by) the root user
[Filters]
-# ironic/drivers/modules/deploy_utils.py
-iscsiadm: CommandFilter, iscsiadm, root
-
# ironic/common/utils.py
mount: CommandFilter, mount, root
umount: CommandFilter, umount, root
diff --git a/ironic/cmd/dbsync.py b/ironic/cmd/dbsync.py
index 071d06a54..81524aa96 100644
--- a/ironic/cmd/dbsync.py
+++ b/ironic/cmd/dbsync.py
@@ -64,8 +64,6 @@ dbapi = db_api.get_instance()
# object, in case it is lazy loaded. The attribute will be accessed when needed
# by doing getattr on the object
ONLINE_MIGRATIONS = (
- # Added in Victoria, remove when removing iscsi deploy.
- (dbapi, 'migrate_from_iscsi_deploy'),
# NOTE(rloo): Don't remove this; it should always be last
(dbapi, 'update_to_latest_versions'),
)
diff --git a/ironic/conf/__init__.py b/ironic/conf/__init__.py
index 2d6fab8db..4e4b7bf7a 100644
--- a/ironic/conf/__init__.py
+++ b/ironic/conf/__init__.py
@@ -35,7 +35,6 @@ from ironic.conf import ilo
from ironic.conf import inspector
from ironic.conf import ipmi
from ironic.conf import irmc
-from ironic.conf import iscsi
from ironic.conf import metrics
from ironic.conf import metrics_statsd
from ironic.conf import molds
@@ -51,6 +50,7 @@ from ironic.conf import xclarity
CONF = cfg.CONF
agent.register_opts(CONF)
+anaconda.register_opts(CONF)
ansible.register_opts(CONF)
api.register_opts(CONF)
audit.register_opts(CONF)
@@ -69,8 +69,6 @@ ilo.register_opts(CONF)
inspector.register_opts(CONF)
ipmi.register_opts(CONF)
irmc.register_opts(CONF)
-iscsi.register_opts(CONF)
-anaconda.register_opts(CONF)
metrics.register_opts(CONF)
metrics_statsd.register_opts(CONF)
molds.register_opts(CONF)
diff --git a/ironic/conf/iscsi.py b/ironic/conf/iscsi.py
deleted file mode 100644
index 5e977e72c..000000000
--- a/ironic/conf/iscsi.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2016 Intel Corporation
-# Copyright 2013 Hewlett-Packard Development Company, L.P.
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# 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. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from oslo_config import cfg
-
-from ironic.common.i18n import _
-
-opts = [
- cfg.PortOpt('portal_port',
- default=3260,
- mutable=True,
- help=_('The port number on which the iSCSI portal listens '
- 'for incoming connections.')),
- cfg.StrOpt('conv_flags',
- mutable=True,
- help=_('Flags that need to be sent to the dd command, '
- 'to control the conversion of the original file '
- 'when copying to the host. It can contain several '
- 'options separated by commas.')),
- cfg.IntOpt('verify_attempts',
- default=3,
- min=1,
- mutable=True,
- help=_('Maximum attempts to verify an iSCSI connection is '
- 'active, sleeping 1 second between attempts. Defaults '
- 'to 3.')),
-]
-
-
-def register_opts(conf):
- conf.register_opts(opts, group='iscsi')
diff --git a/ironic/conf/opts.py b/ironic/conf/opts.py
index 97b9c9d44..607dd8510 100644
--- a/ironic/conf/opts.py
+++ b/ironic/conf/opts.py
@@ -34,7 +34,6 @@ _opts = [
('inspector', ironic.conf.inspector.list_opts()),
('ipmi', ironic.conf.ipmi.opts),
('irmc', ironic.conf.irmc.opts),
- ('iscsi', ironic.conf.iscsi.opts),
('anaconda', ironic.conf.anaconda.opts),
('metrics', ironic.conf.metrics.opts),
('metrics_statsd', ironic.conf.metrics_statsd.opts),
diff --git a/ironic/db/api.py b/ironic/db/api.py
index d44ea73ef..da0838478 100644
--- a/ironic/db/api.py
+++ b/ironic/db/api.py
@@ -974,18 +974,6 @@ class Connection(object, metaclass=abc.ABCMeta):
"""
@abc.abstractmethod
- def migrate_from_iscsi_deploy(self, context, max_count):
- """Tries to migrate away from the iscsi deploy interface.
-
- :param context: the admin context
- :param max_count: The maximum number of objects to migrate. Must be
- >= 0. If zero, all the objects will be migrated.
- :returns: A 2-tuple, 1. the total number of objects that need to be
- migrated (at the beginning of this call) and 2. the number
- of migrated objects.
- """
-
- @abc.abstractmethod
def set_node_traits(self, node_id, traits, version):
"""Replace all of the node traits with specified list of traits.
diff --git a/ironic/db/sqlalchemy/api.py b/ironic/db/sqlalchemy/api.py
index 2029d8942..702755e97 100644
--- a/ironic/db/sqlalchemy/api.py
+++ b/ironic/db/sqlalchemy/api.py
@@ -1578,59 +1578,6 @@ class Connection(api.Connection):
return total_to_migrate, total_migrated
- @oslo_db_api.retry_on_deadlock
- def migrate_from_iscsi_deploy(self, context, max_count, force=False):
- """Tries to migrate away from the iscsi deploy interface.
-
- :param context: the admin context
- :param max_count: The maximum number of objects to migrate. Must be
- >= 0. If zero, all the objects will be migrated.
- :returns: A 2-tuple, 1. the total number of objects that need to be
- migrated (at the beginning of this call) and 2. the number
- of migrated objects.
- """
- # TODO(dtantsur): maybe change to force=True by default in W?
- if not force:
- if 'direct' not in CONF.enabled_deploy_interfaces:
- LOG.warning('The direct deploy interface is not enabled, will '
- 'not migrate nodes to it. Run with --option '
- 'force=true to override.')
- return 0, 0
-
- if CONF.default_deploy_interface == 'iscsi':
- LOG.warning('The iscsi deploy interface is the default, will '
- 'not migrate nodes away from it. Run with '
- '--option force=true to override.')
- return 0, 0
-
- if CONF.agent.image_download_source == 'swift':
- LOG.warning('The direct deploy interface is using swift, will '
- 'not migrate nodes to it. Run with --option '
- 'force=true to override.')
- return 0, 0
-
- total_to_migrate = (model_query(models.Node)
- .filter_by(deploy_interface='iscsi')
- .count())
- if not total_to_migrate:
- return 0, 0
-
- max_to_migrate = max_count or total_to_migrate
-
- with _session_for_write():
- query = (model_query(models.Node.id)
- .filter_by(deploy_interface='iscsi')
- .slice(0, max_to_migrate))
- ids = [row[0] for row in query]
-
- num_migrated = (model_query(models.Node)
- .filter_by(deploy_interface='iscsi')
- .filter(models.Node.id.in_(ids))
- .update({'deploy_interface': 'direct'},
- synchronize_session=False))
-
- return total_to_migrate, num_migrated
-
@staticmethod
def _verify_max_traits_per_node(node_id, num_traits):
"""Verify that an operation would not exceed the per-node trait limit.
diff --git a/ironic/drivers/generic.py b/ironic/drivers/generic.py
index fddd2242c..e0cc13235 100644
--- a/ironic/drivers/generic.py
+++ b/ironic/drivers/generic.py
@@ -23,7 +23,6 @@ from ironic.drivers.modules.ansible import deploy as ansible_deploy
from ironic.drivers.modules import fake
from ironic.drivers.modules import inspector
from ironic.drivers.modules import ipxe
-from ironic.drivers.modules import iscsi_deploy
from ironic.drivers.modules.network import flat as flat_net
from ironic.drivers.modules.network import neutron
from ironic.drivers.modules.network import noop as noop_net
@@ -49,9 +48,9 @@ class GenericHardware(hardware_type.AbstractHardwareType):
@property
def supported_deploy_interfaces(self):
"""List of supported deploy interfaces."""
- return [agent.AgentDeploy, iscsi_deploy.ISCSIDeploy,
- ansible_deploy.AnsibleDeploy, pxe.PXERamdiskDeploy,
- pxe.PXEAnacondaDeploy, agent.CustomAgentDeploy]
+ return [agent.AgentDeploy, ansible_deploy.AnsibleDeploy,
+ pxe.PXERamdiskDeploy, pxe.PXEAnacondaDeploy,
+ agent.CustomAgentDeploy]
@property
def supported_inspect_interfaces(self):
diff --git a/ironic/drivers/modules/agent_client.py b/ironic/drivers/modules/agent_client.py
index 5ca93a3b1..c34855976 100644
--- a/ironic/drivers/modules/agent_client.py
+++ b/ironic/drivers/modules/agent_client.py
@@ -342,34 +342,6 @@ class AgentClient(object):
{'cmd': method, 'node': node.uuid})
return None
- @METRICS.timer('AgentClient.start_iscsi_target')
- def start_iscsi_target(self, node, iqn,
- portal_port=DEFAULT_IPA_PORTAL_PORT,
- wipe_disk_metadata=False):
- """Expose the node's disk as an ISCSI target.
-
- :param node: an Ironic node object
- :param iqn: iSCSI target IQN
- :param portal_port: iSCSI portal port
- :param wipe_disk_metadata: True if the agent should wipe first the
- disk magic strings like the partition
- table, RAID or filesystem signature.
- :raises: IronicException when failed to issue the request or there was
- a malformed response from the agent.
- :raises: AgentAPIError when agent failed to execute specified command.
- :raises: AgentInProgress when the command fails to execute as the agent
- is presently executing the prior command.
- :returns: A dict containing command response from agent.
- See :func:`get_commands_status` for a command result sample.
- """
- params = {'iqn': iqn,
- 'portal_port': portal_port,
- 'wipe_disk_metadata': wipe_disk_metadata}
- return self._command(node=node,
- method='iscsi.start_iscsi_target',
- params=params,
- wait=True)
-
@METRICS.timer('AgentClient.install_bootloader')
def install_bootloader(self, node, root_uuid, target_boot_mode,
efi_system_part_uuid=None,
diff --git a/ironic/drivers/modules/iscsi_deploy.py b/ironic/drivers/modules/iscsi_deploy.py
deleted file mode 100644
index 1f532906b..000000000
--- a/ironic/drivers/modules/iscsi_deploy.py
+++ /dev/null
@@ -1,813 +0,0 @@
-# Copyright 2013 Hewlett-Packard Development Company, L.P.
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# 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. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import contextlib
-import glob
-import os
-import time
-from urllib import parse as urlparse
-
-from ironic_lib import disk_utils
-from ironic_lib import metrics_utils
-from oslo_concurrency import processutils
-from oslo_log import log as logging
-from oslo_utils import excutils
-
-from ironic.common import exception
-from ironic.common.i18n import _
-from ironic.common import states
-from ironic.common import utils
-from ironic.conductor import task_manager
-from ironic.conductor import utils as manager_utils
-from ironic.conf import CONF
-from ironic.drivers import base
-from ironic.drivers.modules import agent_base
-from ironic.drivers.modules import boot_mode_utils
-from ironic.drivers.modules import deploy_utils
-
-LOG = logging.getLogger(__name__)
-
-METRICS = metrics_utils.get_metrics_logger(__name__)
-
-DISK_LAYOUT_PARAMS = ('root_gb', 'swap_mb', 'ephemeral_gb')
-
-
-def _save_disk_layout(node, i_info):
- """Saves the disk layout.
-
- The disk layout used for deployment of the node, is saved.
-
- :param node: the node of interest
- :param i_info: instance information (a dictionary) for the node, containing
- disk layout information
- """
- driver_internal_info = node.driver_internal_info
- driver_internal_info['instance'] = {}
-
- for param in DISK_LAYOUT_PARAMS:
- driver_internal_info['instance'][param] = i_info[param]
-
- node.driver_internal_info = driver_internal_info
- node.save()
-
-
-def discovery(portal_address, portal_port):
- """Do iSCSI discovery on portal."""
- utils.execute('iscsiadm',
- '-m', 'discovery',
- '-t', 'st',
- '-p', '%s:%s' % (utils.wrap_ipv6(portal_address),
- portal_port),
- run_as_root=True,
- attempts=5,
- delay_on_retry=True)
-
-
-def login_iscsi(portal_address, portal_port, target_iqn):
- """Login to an iSCSI target."""
- utils.execute('iscsiadm',
- '-m', 'node',
- '-p', '%s:%s' % (utils.wrap_ipv6(portal_address),
- portal_port),
- '-T', target_iqn,
- '--login',
- run_as_root=True,
- attempts=5,
- delay_on_retry=True)
-
- error_occurred = False
- try:
- # Ensure the login complete
- verify_iscsi_connection(target_iqn)
- # force iSCSI initiator to re-read luns
- force_iscsi_lun_update(target_iqn)
- # ensure file system sees the block device
- check_file_system_for_iscsi_device(portal_address,
- portal_port,
- target_iqn)
- except (exception.InstanceDeployFailure,
- processutils.ProcessExecutionError) as e:
- with excutils.save_and_reraise_exception():
- error_occurred = True
- LOG.error("Failed to login to an iSCSI target due to %s", e)
- finally:
- if error_occurred:
- try:
- logout_iscsi(portal_address, portal_port, target_iqn)
- delete_iscsi(portal_address, portal_port, target_iqn)
- except processutils.ProcessExecutionError as e:
- LOG.warning("An error occurred when trying to cleanup "
- "failed ISCSI session error %s", e)
-
-
-def check_file_system_for_iscsi_device(portal_address,
- portal_port,
- target_iqn):
- """Ensure the file system sees the iSCSI block device."""
- check_dir = "/dev/disk/by-path/ip-%s:%s-iscsi-%s-lun-1" % (portal_address,
- portal_port,
- target_iqn)
- total_checks = CONF.iscsi.verify_attempts
- for attempt in range(total_checks):
- if os.path.exists(check_dir):
- break
- time.sleep(1)
- if LOG.isEnabledFor(logging.DEBUG):
- existing_devs = ', '.join(glob.iglob('/dev/disk/by-path/*iscsi*'))
- LOG.debug("iSCSI connection not seen by file system. Rechecking. "
- "Attempt %(attempt)d out of %(total)d. Available iSCSI "
- "devices: %(devs)s.",
- {"attempt": attempt + 1,
- "total": total_checks,
- "devs": existing_devs})
- else:
- msg = _("iSCSI connection was not seen by the file system after "
- "attempting to verify %d times.") % total_checks
- LOG.error(msg)
- raise exception.InstanceDeployFailure(msg)
-
-
-def verify_iscsi_connection(target_iqn):
- """Verify iscsi connection."""
- LOG.debug("Checking for iSCSI target to become active.")
-
- total_checks = CONF.iscsi.verify_attempts
- for attempt in range(total_checks):
- out, _err = utils.execute('iscsiadm',
- '-m', 'node',
- '-S',
- run_as_root=True)
- if target_iqn in out:
- break
- time.sleep(1)
- LOG.debug("iSCSI connection not active. Rechecking. Attempt "
- "%(attempt)d out of %(total)d",
- {"attempt": attempt + 1, "total": total_checks})
- else:
- msg = _("iSCSI connection did not become active after attempting to "
- "verify %d times.") % total_checks
- LOG.error(msg)
- raise exception.InstanceDeployFailure(msg)
-
-
-def force_iscsi_lun_update(target_iqn):
- """force iSCSI initiator to re-read luns."""
- LOG.debug("Re-reading iSCSI luns.")
- utils.execute('iscsiadm',
- '-m', 'node',
- '-T', target_iqn,
- '-R',
- run_as_root=True)
-
-
-def logout_iscsi(portal_address, portal_port, target_iqn):
- """Logout from an iSCSI target."""
- utils.execute('iscsiadm',
- '-m', 'node',
- '-p', '%s:%s' % (utils.wrap_ipv6(portal_address),
- portal_port),
- '-T', target_iqn,
- '--logout',
- run_as_root=True,
- attempts=5,
- delay_on_retry=True)
-
-
-def delete_iscsi(portal_address, portal_port, target_iqn):
- """Delete the iSCSI target."""
- # Retry delete until it succeeds (exit code 0) or until there is
- # no longer a target to delete (exit code 21).
- utils.execute('iscsiadm',
- '-m', 'node',
- '-p', '%s:%s' % (utils.wrap_ipv6(portal_address),
- portal_port),
- '-T', target_iqn,
- '-o', 'delete',
- run_as_root=True,
- check_exit_code=[0, 21],
- attempts=5,
- delay_on_retry=True)
-
-
-@contextlib.contextmanager
-def _iscsi_setup_and_handle_errors(address, port, iqn, lun):
- """Function that yields an iSCSI target device to work on.
-
- :param address: The iSCSI IP address.
- :param port: The iSCSI port number.
- :param iqn: The iSCSI qualified name.
- :param lun: The iSCSI logical unit number.
- """
- dev = ("/dev/disk/by-path/ip-%s:%s-iscsi-%s-lun-%s"
- % (address, port, iqn, lun))
- discovery(address, port)
- login_iscsi(address, port, iqn)
- if not disk_utils.is_block_device(dev):
- raise exception.InstanceDeployFailure(_("Parent device '%s' not found")
- % dev)
- try:
- yield dev
- except processutils.ProcessExecutionError as err:
- with excutils.save_and_reraise_exception():
- LOG.error("Deploy to address %s failed.", address)
- LOG.error("Command: %s", err.cmd)
- LOG.error("StdOut: %r", err.stdout)
- LOG.error("StdErr: %r", err.stderr)
- except exception.InstanceDeployFailure as e:
- with excutils.save_and_reraise_exception():
- LOG.error("Deploy to address %s failed.", address)
- LOG.error(e)
- finally:
- logout_iscsi(address, port, iqn)
- delete_iscsi(address, port, iqn)
-
-
-def deploy_partition_image(
- address, port, iqn, lun, image_path,
- root_mb, swap_mb, ephemeral_mb, ephemeral_format, node_uuid,
- preserve_ephemeral=False, configdrive=None,
- boot_option=None, boot_mode="bios", disk_label=None,
- cpu_arch=""):
- """All-in-one function to deploy a partition image to a node.
-
- :param address: The iSCSI IP address.
- :param port: The iSCSI port number.
- :param iqn: The iSCSI qualified name.
- :param lun: The iSCSI logical unit number.
- :param image_path: Path for the instance's disk image.
- :param root_mb: Size of the root partition in megabytes.
- :param swap_mb: Size of the swap partition in megabytes.
- :param ephemeral_mb: Size of the ephemeral partition in megabytes. If 0,
- no ephemeral partition will be created.
- :param ephemeral_format: The type of file system to format the ephemeral
- partition.
- :param node_uuid: node's uuid. Used for logging.
- :param preserve_ephemeral: If True, no filesystem is written to the
- ephemeral block device, preserving whatever
- content it had (if the partition table has
- not changed).
- :param configdrive: Optional. Base64 encoded Gzipped configdrive content
- or configdrive HTTP URL.
- :param boot_option: Can be "local" or "netboot".
- "netboot" by default.
- :param boot_mode: Can be "bios" or "uefi". "bios" by default.
- :param disk_label: The disk label to be used when creating the
- partition table. Valid values are: "msdos",
- "gpt" or None; If None ironic will figure it
- out according to the boot_mode parameter.
- :param cpu_arch: Architecture of the node being deployed to.
- :raises: InstanceDeployFailure if image virtual size is bigger than root
- partition size.
- :returns: a dictionary containing the following keys:
- 'root uuid': UUID of root partition
- 'efi system partition uuid': UUID of the uefi system partition
- (if boot mode is uefi).
- NOTE: If key exists but value is None, it means partition doesn't
- exist.
- """
- # NOTE(dtantsur): CONF.default_boot_option is mutable, don't use it in
- # the function signature!
- boot_option = boot_option or deploy_utils.get_default_boot_option()
- image_mb = disk_utils.get_image_mb(image_path)
- if image_mb > root_mb:
- msg = (_('Root partition is too small for requested image. Image '
- 'virtual size: %(image_mb)d MB, Root size: %(root_mb)d MB')
- % {'image_mb': image_mb, 'root_mb': root_mb})
- raise exception.InstanceDeployFailure(msg)
-
- with _iscsi_setup_and_handle_errors(address, port, iqn, lun) as dev:
- uuid_dict_returned = disk_utils.work_on_disk(
- dev, root_mb, swap_mb, ephemeral_mb, ephemeral_format, image_path,
- node_uuid, preserve_ephemeral=preserve_ephemeral,
- configdrive=configdrive, boot_option=boot_option,
- boot_mode=boot_mode, disk_label=disk_label, cpu_arch=cpu_arch)
-
- return uuid_dict_returned
-
-
-def deploy_disk_image(address, port, iqn, lun,
- image_path, node_uuid, configdrive=None,
- conv_flags=None):
- """All-in-one function to deploy a whole disk image to a node.
-
- :param address: The iSCSI IP address.
- :param port: The iSCSI port number.
- :param iqn: The iSCSI qualified name.
- :param lun: The iSCSI logical unit number.
- :param image_path: Path for the instance's disk image.
- :param node_uuid: node's uuid.
- :param configdrive: Optional. Base64 encoded Gzipped configdrive content
- or configdrive HTTP URL.
- :param conv_flags: Optional. Add a flag that will modify the behaviour of
- the image copy to disk.
- :returns: a dictionary containing the key 'disk identifier' to identify
- the disk which was used for deployment.
- """
- with _iscsi_setup_and_handle_errors(address, port, iqn,
- lun) as dev:
- disk_utils.populate_image(image_path, dev, conv_flags=conv_flags)
-
- if configdrive:
- disk_utils.create_config_drive_partition(node_uuid, dev,
- configdrive)
-
- disk_identifier = disk_utils.get_disk_identifier(dev)
-
- return {'disk identifier': disk_identifier}
-
-
-@METRICS.timer('check_image_size')
-def check_image_size(task):
- """Check if the requested image is larger than the root partition size.
-
- Does nothing for whole-disk images.
-
- :param task: a TaskManager instance containing the node to act on.
- :raises: InstanceDeployFailure if size of the image is greater than root
- partition.
- """
- if task.node.driver_internal_info['is_whole_disk_image']:
- # The root partition is already created and populated, no use
- # validating its size
- return
-
- i_info = deploy_utils.parse_instance_info(task.node)
- image_path = deploy_utils._get_image_file_path(task.node.uuid)
- image_mb = disk_utils.get_image_mb(image_path)
- root_mb = 1024 * int(i_info['root_gb'])
- if image_mb > root_mb:
- msg = (_('Root partition is too small for requested image. Image '
- 'virtual size: %(image_mb)d MB, Root size: %(root_mb)d MB')
- % {'image_mb': image_mb, 'root_mb': root_mb})
- raise exception.InstanceDeployFailure(msg)
-
-
-@METRICS.timer('get_deploy_info')
-def get_deploy_info(node, address, iqn, port=None, lun='1', conv_flags=None):
- """Returns the information required for doing iSCSI deploy in a dictionary.
-
- :param node: ironic node object
- :param address: iSCSI address
- :param iqn: iSCSI iqn for the target disk
- :param port: iSCSI port, defaults to one specified in the configuration
- :param lun: iSCSI lun, defaults to '1'
- :param conv_flags: flag that will modify the behaviour of the image copy
- to disk.
- :raises: MissingParameterValue, if some required parameters were not
- passed.
- :raises: InvalidParameterValue, if any of the parameters have invalid
- value.
- """
- i_info = deploy_utils.parse_instance_info(node)
-
- params = {
- 'address': address,
- 'port': port or CONF.iscsi.portal_port,
- 'iqn': iqn,
- 'lun': lun,
- 'image_path': deploy_utils._get_image_file_path(node.uuid),
- 'node_uuid': node.uuid}
-
- is_whole_disk_image = node.driver_internal_info['is_whole_disk_image']
- if not is_whole_disk_image:
- params.update({'root_mb': i_info['root_mb'],
- 'swap_mb': i_info['swap_mb'],
- 'ephemeral_mb': i_info['ephemeral_mb'],
- 'preserve_ephemeral': i_info['preserve_ephemeral'],
- 'boot_option': deploy_utils.get_boot_option(node),
- 'boot_mode': boot_mode_utils.get_boot_mode(node)})
-
- cpu_arch = node.properties.get('cpu_arch')
- if cpu_arch is not None:
- params['cpu_arch'] = cpu_arch
-
- # Append disk label if specified
- disk_label = deploy_utils.get_disk_label(node)
- if disk_label is not None:
- params['disk_label'] = disk_label
-
- missing = [key for key in params if params[key] is None]
- if missing:
- raise exception.MissingParameterValue(
- _("Parameters %s were not passed to ironic"
- " for deploy.") % missing)
-
- # configdrive is nullable
- params['configdrive'] = i_info.get('configdrive')
- if is_whole_disk_image:
- return params
-
- if conv_flags:
- params['conv_flags'] = conv_flags
-
- # ephemeral_format is nullable
- params['ephemeral_format'] = i_info.get('ephemeral_format')
-
- return params
-
-
-@METRICS.timer('continue_deploy')
-def continue_deploy(task, **kwargs):
- """Resume a deployment upon getting POST data from deploy ramdisk.
-
- This method raises no exceptions because it is intended to be
- invoked asynchronously as a callback from the deploy ramdisk.
-
- :param task: a TaskManager instance containing the node to act on.
- :param kwargs: the kwargs to be passed to deploy.
- :raises: InvalidState if the event is not allowed by the associated
- state machine.
- :returns: a dictionary containing the following keys:
-
- For partition image:
-
- * 'root uuid': UUID of root partition
- * 'efi system partition uuid': UUID of the uefi system partition
- (if boot mode is uefi).
-
- .. note:: If key exists but value is None, it means partition
- doesn't exist.
-
- For whole disk image:
-
- * 'disk identifier': ID of the disk to which image was deployed.
- """
- node = task.node
-
- params = get_deploy_info(node, **kwargs)
-
- def _fail_deploy(task, msg, raise_exception=True):
- """Fail the deploy after logging and setting error states."""
- if isinstance(msg, Exception):
- msg = (_('Deploy failed for instance %(instance)s. '
- 'Error: %(error)s') %
- {'instance': node.instance_uuid, 'error': msg})
- deploy_utils.set_failed_state(task, msg)
- deploy_utils.destroy_images(task.node.uuid)
- if raise_exception:
- raise exception.InstanceDeployFailure(msg)
-
- # NOTE(lucasagomes): Let's make sure we don't log the full content
- # of the config drive here because it can be up to 64MB in size,
- # so instead let's log "***" in case config drive is enabled.
- if LOG.isEnabledFor(logging.logging.DEBUG):
- log_params = {
- k: params[k] if k != 'configdrive' else '***'
- for k in params
- }
- LOG.debug('Continuing deployment for node %(node)s, params %(params)s',
- {'node': node.uuid, 'params': log_params})
-
- uuid_dict_returned = {}
- try:
- if node.driver_internal_info['is_whole_disk_image']:
- uuid_dict_returned = deploy_disk_image(**params)
- else:
- uuid_dict_returned = deploy_partition_image(**params)
- except exception.IronicException as e:
- with excutils.save_and_reraise_exception():
- LOG.error('Deploy of instance %(instance)s on node %(node)s '
- 'failed: %(error)s', {'instance': node.instance_uuid,
- 'node': node.uuid, 'error': e})
- _fail_deploy(task, e, raise_exception=False)
- except Exception as e:
- LOG.exception('Deploy of instance %(instance)s on node %(node)s '
- 'failed with exception',
- {'instance': node.instance_uuid, 'node': node.uuid})
- _fail_deploy(task, e)
-
- root_uuid_or_disk_id = uuid_dict_returned.get(
- 'root uuid', uuid_dict_returned.get('disk identifier'))
- if not root_uuid_or_disk_id:
- msg = (_("Couldn't determine the UUID of the root "
- "partition or the disk identifier after deploying "
- "node %s") % node.uuid)
- LOG.error(msg)
- _fail_deploy(task, msg)
-
- if params.get('preserve_ephemeral', False):
- # Save disk layout information, to check that they are unchanged
- # for any future rebuilds
- _save_disk_layout(node, deploy_utils.parse_instance_info(node))
-
- deploy_utils.destroy_images(node.uuid)
- return uuid_dict_returned
-
-
-@METRICS.timer('do_agent_iscsi_deploy')
-def do_agent_iscsi_deploy(task, agent_client):
- """Method invoked when deployed with the agent ramdisk.
-
- This method is invoked by drivers for doing iSCSI deploy
- using agent ramdisk. This method assumes that the agent
- is booted up on the node and is heartbeating.
-
- :param task: a TaskManager object containing the node.
- :param agent_client: an instance of agent_client.AgentClient
- which will be used during iscsi deploy
- (for exposing node's target disk via iSCSI,
- for install boot loader, etc).
- :returns: a dictionary containing the following keys:
-
- For partition image:
-
- * 'root uuid': UUID of root partition
- * 'efi system partition uuid': UUID of the uefi system partition
- (if boot mode is uefi).
-
- .. note:: If key exists but value is None, it means partition
- doesn't exist.
-
- For whole disk image:
-
- * 'disk identifier': ID of the disk to which image was deployed.
- :raises: InstanceDeployFailure if it encounters some error
- during the deploy.
- """
- node = task.node
- i_info = deploy_utils.parse_instance_info(node)
- wipe_disk_metadata = not i_info['preserve_ephemeral']
-
- iqn = 'iqn.2008-10.org.openstack:%s' % node.uuid
- portal_port = CONF.iscsi.portal_port
- conv_flags = CONF.iscsi.conv_flags
- result = agent_client.start_iscsi_target(
- node, iqn,
- portal_port,
- wipe_disk_metadata=wipe_disk_metadata)
- if result['command_status'] == 'FAILED':
- msg = (_("Failed to start the iSCSI target to deploy the "
- "node %(node)s. Error: %(error)s") %
- {'node': node.uuid, 'error': result['command_error']})
- deploy_utils.set_failed_state(task, msg)
- raise exception.InstanceDeployFailure(reason=msg)
-
- address = urlparse.urlparse(node.driver_internal_info['agent_url'])
- address = address.hostname
-
- uuid_dict_returned = continue_deploy(task, iqn=iqn, address=address,
- conv_flags=conv_flags)
- root_uuid_or_disk_id = uuid_dict_returned.get(
- 'root uuid', uuid_dict_returned.get('disk identifier'))
-
- # TODO(lucasagomes): Move this bit saving the root_uuid to
- # continue_deploy()
- driver_internal_info = node.driver_internal_info
- driver_internal_info['root_uuid_or_disk_id'] = root_uuid_or_disk_id
- node.driver_internal_info = driver_internal_info
- node.save()
-
- return uuid_dict_returned
-
-
-@METRICS.timer('validate')
-def validate(task):
- """Validates the pre-requisites for iSCSI deploy.
-
- Validates whether node in the task provided has some ports enrolled.
- This method validates whether conductor url is available either from CONF
- file or from keystone.
-
- :param task: a TaskManager instance containing the node to act on.
- :raises: InvalidParameterValue if the URL of the Ironic API service is not
- configured in config file and is not accessible via Keystone
- catalog.
- :raises: MissingParameterValue if no ports are enrolled for the given node.
- """
- # TODO(lucasagomes): Validate the format of the URL
- deploy_utils.get_ironic_api_url()
- # Validate the root device hints
- deploy_utils.get_root_device_for_deploy(task.node)
- deploy_utils.parse_instance_info(task.node)
-
-
-class ISCSIDeploy(agent_base.AgentDeployMixin, agent_base.AgentBaseMixin,
- base.DeployInterface):
- """iSCSI Deploy Interface for deploy-related actions."""
-
- has_decomposed_deploy_steps = True
-
- supported = False
-
- def get_properties(self):
- return agent_base.VENDOR_PROPERTIES
-
- @METRICS.timer('ISCSIDeploy.validate')
- def validate(self, task):
- """Validate the deployment information for the task's node.
-
- :param task: a TaskManager instance containing the node to act on.
- :raises: InvalidParameterValue.
- :raises: MissingParameterValue
- """
- task.driver.boot.validate(task)
- node = task.node
-
- # Check the boot_mode, boot_option and disk_label capabilities values.
- deploy_utils.validate_capabilities(node)
-
- # Edit early if we are not writing a volume as the validate
- # tasks evaluate root device hints.
- if not task.driver.storage.should_write_image(task):
- LOG.debug('Skipping complete deployment interface validation '
- 'for node %s as it is set to boot from a remote '
- 'volume.', node.uuid)
- return
-
- # TODO(rameshg87): iscsi_ilo driver used to call this function. Remove
- # and copy-paste it's contents here.
- validate(task)
-
- @METRICS.timer('ISCSIDeploy.deploy')
- @base.deploy_step(priority=100)
- @task_manager.require_exclusive_lock
- def deploy(self, task):
- """Start deployment of the task's node.
-
- Fetches instance image, updates the DHCP port options for next boot,
- and issues a reboot request to the power driver.
- This causes the node to boot into the deployment ramdisk and triggers
- the next phase of PXE-based deployment via agent heartbeats.
-
- :param task: a TaskManager instance containing the node to act on.
- :returns: deploy state DEPLOYWAIT.
- """
- node = task.node
- if manager_utils.is_fast_track(task):
- # NOTE(mgoddard): For fast track we can mostly skip this step and
- # proceed to the next step (i.e. write_image).
- LOG.debug('Performing a fast track deployment for %(node)s.',
- {'node': task.node.uuid})
- deploy_utils.cache_instance_image(task.context, node)
- check_image_size(task)
- # NOTE(dtantsur): while the node is up and heartbeating, we don't
- # necessary have the deploy steps cached. Force a refresh here.
- self.refresh_steps(task, 'deploy')
- elif task.driver.storage.should_write_image(task):
- # Standard deploy process
- deploy_utils.cache_instance_image(task.context, node)
- check_image_size(task)
- # Check if the driver has already performed a reboot in a previous
- # deploy step.
- if not task.node.driver_internal_info.get('deployment_reboot',
- False):
- manager_utils.node_power_action(task, states.REBOOT)
- info = task.node.driver_internal_info
- info.pop('deployment_reboot', None)
- info.pop('deployment_uuids', None)
- task.node.driver_internal_info = info
- task.node.save()
-
- return states.DEPLOYWAIT
-
- @METRICS.timer('ISCSIDeploy.write_image')
- @base.deploy_step(priority=80)
- @task_manager.require_exclusive_lock
- def write_image(self, task):
- """Method invoked when deployed using iSCSI.
-
- This method is invoked during a heartbeat from an agent when
- the node is in wait-call-back state. This deploys the image on
- the node and then configures the node to boot according to the
- desired boot option (netboot or localboot).
-
- :param task: a TaskManager object containing the node.
- :param kwargs: the kwargs passed from the heartbeat method.
- :raises: InstanceDeployFailure, if it encounters some error during
- the deploy.
- """
- if not task.driver.storage.should_write_image(task):
- LOG.debug('Skipping write_image for node %s', task.node.uuid)
- return
-
- node = task.node
- LOG.debug('Continuing the deployment on node %s', node.uuid)
- if utils.is_memory_insufficent():
- # Insufficent memory, but we can just let the agent heartbeat
- # again in order to initiate deployment when the situation has
- # changed.
- LOG.warning('Insufficent memory to write image for node '
- '%(node)s. Skipping until next heartbeat.',
- {'node': node.uuid})
- info = node.driver_internal_info
- info['skip_current_deploy_step'] = False
- node.driver_internal_info = info
- node.last_error = "Deploy delayed due to insufficent memory"
- node.save()
- return states.DEPLOYWAIT
- uuid_dict_returned = do_agent_iscsi_deploy(task, self._client)
- utils.set_node_nested_field(node, 'driver_internal_info',
- 'deployment_uuids', uuid_dict_returned)
- node.save()
-
- @METRICS.timer('ISCSIDeploy.prepare_instance_boot')
- @base.deploy_step(priority=60)
- def prepare_instance_boot(self, task):
- if not task.driver.storage.should_write_image(task):
- task.driver.boot.prepare_instance(task)
- return
-
- node = task.node
- try:
- uuid_dict_returned = node.driver_internal_info['deployment_uuids']
- except KeyError:
- raise exception.InstanceDeployFailure(
- _('Invalid internal state: the write_image deploy step has '
- 'not been called before prepare_instance_boot'))
- root_uuid = uuid_dict_returned.get('root uuid')
- efi_sys_uuid = uuid_dict_returned.get('efi system partition uuid')
- prep_boot_part_uuid = uuid_dict_returned.get(
- 'PrEP Boot partition uuid')
-
- self.prepare_instance_to_boot(task, root_uuid, efi_sys_uuid,
- prep_boot_part_uuid=prep_boot_part_uuid)
-
- @METRICS.timer('ISCSIDeploy.prepare')
- @task_manager.require_exclusive_lock
- def prepare(self, task):
- """Prepare the deployment environment for this task's node.
-
- Generates the TFTP configuration for PXE-booting both the deployment
- and user images, fetches the TFTP image from Glance and add it to the
- local cache.
-
- :param task: a TaskManager instance containing the node to act on.
- :raises: NetworkError: if the previous cleaning ports cannot be removed
- or if new cleaning ports cannot be created.
- :raises: InvalidParameterValue when the wrong power state is specified
- or the wrong driver info is specified for power management.
- :raises: StorageError If the storage driver is unable to attach the
- configured volumes.
- :raises: other exceptions by the node's power driver if something
- wrong occurred during the power action.
- :raises: any boot interface's prepare_ramdisk exceptions.
- """
- node = task.node
- deploy_utils.populate_storage_driver_internal_info(task)
- if node.provision_state in [states.ACTIVE, states.ADOPTING]:
- task.driver.boot.prepare_instance(task)
- else:
- if node.provision_state == states.DEPLOYING:
- fast_track_deploy = manager_utils.is_fast_track(task)
- if fast_track_deploy:
- # The agent has already recently checked in and we are
- # configured to take that as an indicator that we can
- # skip ahead.
- LOG.debug('The agent for node %(node)s has recently '
- 'checked in, and the node power will remain '
- 'unmodified.',
- {'node': task.node.uuid})
- else:
- # Adding the node to provisioning network so that the dhcp
- # options get added for the provisioning port.
- manager_utils.node_power_action(task, states.POWER_OFF)
- # NOTE(vdrok): in case of rebuild, we have tenant network
- # already configured, unbind tenant ports if present
- if task.driver.storage.should_write_image(task):
- if not fast_track_deploy:
- power_state_to_restore = (
- manager_utils.power_on_node_if_needed(task))
- task.driver.network.unconfigure_tenant_networks(task)
- task.driver.network.add_provisioning_network(task)
- if not fast_track_deploy:
- manager_utils.restore_power_state_if_needed(
- task, power_state_to_restore)
- task.driver.storage.attach_volumes(task)
- if (not task.driver.storage.should_write_image(task)
- or fast_track_deploy):
- # We have nothing else to do as this is handled in the
- # backend storage system, and we can return to the caller
- # as we do not need to boot the agent to deploy.
- # Alternatively, we are in a fast track deployment
- # and have nothing else to do.
- return
-
- deploy_opts = deploy_utils.build_agent_options(node)
- task.driver.boot.prepare_ramdisk(task, deploy_opts)
-
- @METRICS.timer('ISCSIDeploy.clean_up')
- def clean_up(self, task):
- """Clean up the deployment environment for the task's node.
-
- Unlinks TFTP and instance images and triggers image cache cleanup.
- Removes the TFTP configuration files for this node.
-
- :param task: a TaskManager instance containing the node to act on.
- """
- deploy_utils.destroy_images(task.node.uuid)
- super(ISCSIDeploy, self).clean_up(task)
- if utils.pop_node_nested_field(task.node, 'driver_internal_info',
- 'deployment_uuids'):
- task.node.save()
diff --git a/ironic/objects/conductor.py b/ironic/objects/conductor.py
index ad381359b..307e218c5 100644
--- a/ironic/objects/conductor.py
+++ b/ironic/objects/conductor.py
@@ -163,7 +163,7 @@ class Conductor(base.IronicObject, object_base.VersionedObjectDictCompat):
be a dictionary conaining "hardware_type", "interface_type",
"interface_name" and "default", e.g.
{'hardware_type': 'hardware-type', 'interface_type': 'deploy',
- 'interface_name': 'iscsi', 'default': True}
+ 'interface_name': 'direct', 'default': True}
"""
self.dbapi.register_conductor_hardware_interfaces(self.id, interfaces)
diff --git a/ironic/tests/base.py b/ironic/tests/base.py
index f5000d0be..9952ec18e 100644
--- a/ironic/tests/base.py
+++ b/ironic/tests/base.py
@@ -159,7 +159,7 @@ class TestCase(oslo_test_base.BaseTestCase):
values = ['fake']
if iface == 'deploy':
- values.extend(['iscsi', 'direct', 'anaconda'])
+ values.extend(['direct', 'anaconda'])
elif iface == 'boot':
values.append('pxe')
elif iface == 'storage':
diff --git a/ironic/tests/unit/api/controllers/v1/test_driver.py b/ironic/tests/unit/api/controllers/v1/test_driver.py
index 781b22bf0..b991ac7af 100644
--- a/ironic/tests/unit/api/controllers/v1/test_driver.py
+++ b/ironic/tests/unit/api/controllers/v1/test_driver.py
@@ -46,14 +46,14 @@ class TestListDrivers(base.BaseApiTest):
self.dbapi.register_conductor_hardware_interfaces(
c.id,
[{'hardware_type': self.hw1, 'interface_type': 'deploy',
- 'interface_name': 'iscsi', 'default': False},
+ 'interface_name': 'ansible', 'default': False},
{'hardware_type': self.hw1, 'interface_type': 'deploy',
'interface_name': 'direct', 'default': True}]
)
self.dbapi.register_conductor_hardware_interfaces(
c1.id,
[{'hardware_type': self.hw2, 'interface_type': 'deploy',
- 'interface_name': 'iscsi', 'default': False},
+ 'interface_name': 'ansible', 'default': False},
{'hardware_type': self.hw2, 'interface_type': 'deploy',
'interface_name': 'direct', 'default': True}]
)
@@ -124,7 +124,7 @@ class TestListDrivers(base.BaseApiTest):
{
'hardware_type': self.hw1,
'interface_type': 'deploy',
- 'interface_name': 'iscsi',
+ 'interface_name': 'ansible',
'default': False,
},
{
@@ -238,7 +238,7 @@ class TestListDrivers(base.BaseApiTest):
{
'hardware_type': self.hw1,
'interface_type': 'deploy',
- 'interface_name': 'iscsi',
+ 'interface_name': 'ansible',
'default': False,
},
{
diff --git a/ironic/tests/unit/common/test_hash_ring.py b/ironic/tests/unit/common/test_hash_ring.py
index 7e05aabff..9ecf34562 100644
--- a/ironic/tests/unit/common/test_hash_ring.py
+++ b/ironic/tests/unit/common/test_hash_ring.py
@@ -61,7 +61,7 @@ class HashRingManagerTestCase(db_base.DbTestCase):
self.dbapi.register_conductor_hardware_interfaces(
c.id,
[{'hardware_type': 'hardware-type', 'interface_type': 'deploy',
- 'interface_name': 'iscsi', 'default': True},
+ 'interface_name': 'ansible', 'default': True},
{'hardware_type': 'hardware-type', 'interface_type': 'deploy',
'interface_name': 'direct', 'default': False}]
)
@@ -107,7 +107,7 @@ class HashRingManagerTestCase(db_base.DbTestCase):
self.dbapi.register_conductor_hardware_interfaces(
c1.id,
[{'hardware_type': 'hardware-type', 'interface_type': 'deploy',
- 'interface_name': 'iscsi', 'default': True},
+ 'interface_name': 'ansible', 'default': True},
{'hardware_type': 'hardware-type', 'interface_type': 'deploy',
'interface_name': 'direct', 'default': False}]
)
@@ -118,7 +118,7 @@ class HashRingManagerTestCase(db_base.DbTestCase):
self.dbapi.register_conductor_hardware_interfaces(
c2.id,
[{'hardware_type': 'hardware-type', 'interface_type': 'deploy',
- 'interface_name': 'iscsi', 'default': True},
+ 'interface_name': 'ansible', 'default': True},
{'hardware_type': 'hardware-type', 'interface_type': 'deploy',
'interface_name': 'direct', 'default': False}]
)
diff --git a/ironic/tests/unit/conductor/test_base_manager.py b/ironic/tests/unit/conductor/test_base_manager.py
index 0ee6e9160..886ab07ed 100644
--- a/ironic/tests/unit/conductor/test_base_manager.py
+++ b/ironic/tests/unit/conductor/test_base_manager.py
@@ -411,14 +411,14 @@ class RegisterInterfacesTestCase(mgr_utils.ServiceSetUpMixin,
esi_mock.side_effect = [
collections.OrderedDict((
('management', ['fake', 'noop']),
- ('deploy', ['agent', 'iscsi']),
+ ('deploy', ['direct', 'ansible']),
)),
collections.OrderedDict((
('management', ['fake']),
- ('deploy', ['agent', 'fake']),
+ ('deploy', ['direct', 'fake']),
)),
]
- default_mock.side_effect = ('fake', 'agent', 'fake', 'agent')
+ default_mock.side_effect = ('fake', 'direct', 'fake', 'direct')
expected_calls = [
mock.call(
mock.ANY,
@@ -432,11 +432,11 @@ class RegisterInterfacesTestCase(mgr_utils.ServiceSetUpMixin,
'default': False},
{'hardware_type': 'fake-hardware',
'interface_type': 'deploy',
- 'interface_name': 'agent',
+ 'interface_name': 'direct',
'default': True},
{'hardware_type': 'fake-hardware',
'interface_type': 'deploy',
- 'interface_name': 'iscsi',
+ 'interface_name': 'ansible',
'default': False},
{'hardware_type': 'manual-management',
'interface_type': 'management',
@@ -444,7 +444,7 @@ class RegisterInterfacesTestCase(mgr_utils.ServiceSetUpMixin,
'default': True},
{'hardware_type': 'manual-management',
'interface_type': 'deploy',
- 'interface_name': 'agent',
+ 'interface_name': 'direct',
'default': True},
{'hardware_type': 'manual-management',
'interface_type': 'deploy',
@@ -471,7 +471,7 @@ class RegisterInterfacesTestCase(mgr_utils.ServiceSetUpMixin,
esi_mock.side_effect = [
collections.OrderedDict((
('management', ['fake', 'noop']),
- ('deploy', ['agent', 'iscsi']),
+ ('deploy', ['direct', 'ansible']),
)),
]
default_mock.side_effect = exception.NoValidDefaultForInterface("boo")
diff --git a/ironic/tests/unit/conductor/test_manager.py b/ironic/tests/unit/conductor/test_manager.py
index 48c62d613..8b60e7c64 100644
--- a/ironic/tests/unit/conductor/test_manager.py
+++ b/ironic/tests/unit/conductor/test_manager.py
@@ -713,7 +713,7 @@ class UpdateNodeTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
IFACE_UPDATE_DICT = {
'boot_interface': UpdateInterfaces('pxe', 'fake'),
'console_interface': UpdateInterfaces('no-console', 'fake'),
- 'deploy_interface': UpdateInterfaces('iscsi', 'fake'),
+ 'deploy_interface': UpdateInterfaces('direct', 'fake'),
'inspect_interface': UpdateInterfaces('no-inspect', 'fake'),
'management_interface': UpdateInterfaces(None, 'fake'),
'network_interface': UpdateInterfaces('noop', 'flat'),
@@ -984,7 +984,7 @@ class UpdateNodeTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
deploy_interface='fake',
extra={'test': 'one'})
- node.deploy_interface = 'iscsi'
+ node.deploy_interface = 'direct'
exc = self.assertRaises(messaging.rpc.ExpectedException,
self.service.update_node,
self.context, node)
diff --git a/ironic/tests/unit/conductor/test_rpcapi.py b/ironic/tests/unit/conductor/test_rpcapi.py
index 5624c6439..0c7763e83 100644
--- a/ironic/tests/unit/conductor/test_rpcapi.py
+++ b/ironic/tests/unit/conductor/test_rpcapi.py
@@ -84,7 +84,7 @@ class RPCAPITestCase(db_base.DbTestCase):
self.dbapi.register_conductor_hardware_interfaces(
c.id,
[{'hardware_type': 'fake-driver', 'interface_type': 'deploy',
- 'interface_name': 'iscsi', 'default': True},
+ 'interface_name': 'ansible', 'default': True},
{'hardware_type': 'fake-driver', 'interface_type': 'deploy',
'interface_name': 'direct', 'default': False}]
)
@@ -101,7 +101,7 @@ class RPCAPITestCase(db_base.DbTestCase):
self.dbapi.register_conductor_hardware_interfaces(
c.id,
[{'hardware_type': 'other-driver', 'interface_type': 'deploy',
- 'interface_name': 'iscsi', 'default': True},
+ 'interface_name': 'ansible', 'default': True},
{'hardware_type': 'other-driver', 'interface_type': 'deploy',
'interface_name': 'direct', 'default': False}]
)
@@ -124,7 +124,7 @@ class RPCAPITestCase(db_base.DbTestCase):
self.dbapi.register_conductor_hardware_interfaces(
c.id,
[{'hardware_type': 'fake-driver', 'interface_type': 'deploy',
- 'interface_name': 'iscsi', 'default': True},
+ 'interface_name': 'ansible', 'default': True},
{'hardware_type': 'fake-driver', 'interface_type': 'deploy',
'interface_name': 'direct', 'default': False}]
)
@@ -143,7 +143,7 @@ class RPCAPITestCase(db_base.DbTestCase):
self.dbapi.register_conductor_hardware_interfaces(
c.id,
[{'hardware_type': 'fake-driver', 'interface_type': 'deploy',
- 'interface_name': 'iscsi', 'default': True},
+ 'interface_name': 'ansible', 'default': True},
{'hardware_type': 'fake-driver', 'interface_type': 'deploy',
'interface_name': 'direct', 'default': False}]
)
@@ -160,7 +160,7 @@ class RPCAPITestCase(db_base.DbTestCase):
self.dbapi.register_conductor_hardware_interfaces(
c.id,
[{'hardware_type': 'fake-driver', 'interface_type': 'deploy',
- 'interface_name': 'iscsi', 'default': True},
+ 'interface_name': 'ansible', 'default': True},
{'hardware_type': 'fake-driver', 'interface_type': 'deploy',
'interface_name': 'direct', 'default': False}]
)
@@ -183,7 +183,7 @@ class RPCAPITestCase(db_base.DbTestCase):
self.dbapi.register_conductor_hardware_interfaces(
c.id,
[{'hardware_type': 'fake-driver', 'interface_type': 'deploy',
- 'interface_name': 'iscsi', 'default': True},
+ 'interface_name': 'ansible', 'default': True},
{'hardware_type': 'fake-driver', 'interface_type': 'deploy',
'interface_name': 'direct', 'default': False}]
)
@@ -198,7 +198,7 @@ class RPCAPITestCase(db_base.DbTestCase):
self.dbapi.register_conductor_hardware_interfaces(
c.id,
[{'hardware_type': 'fake-driver', 'interface_type': 'deploy',
- 'interface_name': 'iscsi', 'default': True},
+ 'interface_name': 'ansible', 'default': True},
{'hardware_type': 'fake-driver', 'interface_type': 'deploy',
'interface_name': 'direct', 'default': False}]
)
diff --git a/ironic/tests/unit/db/test_api.py b/ironic/tests/unit/db/test_api.py
index 701d1afc4..f855e9c91 100644
--- a/ironic/tests/unit/db/test_api.py
+++ b/ironic/tests/unit/db/test_api.py
@@ -237,73 +237,3 @@ class UpdateToLatestVersionsTestCase(base.DbTestCase):
for uuid in nodes:
node = self.dbapi.get_node_by_uuid(uuid)
self.assertEqual(self.node_ver, node.version)
-
-
-class MigrateFromIscsiTestCase(base.DbTestCase):
-
- def setUp(self):
- super(MigrateFromIscsiTestCase, self).setUp()
- self.context = context.get_admin_context()
- self.dbapi = db_api.get_instance()
- self.config(enabled_deploy_interfaces='direct')
-
- def test_empty_db(self):
- self.assertEqual(
- (0, 0), self.dbapi.migrate_from_iscsi_deploy(self.context, 10))
-
- def test_already_direct_exists(self):
- utils.create_test_node(deploy_interface='direct')
- self.assertEqual(
- (0, 0), self.dbapi.update_to_latest_versions(self.context, 10))
-
- def test_migrate_by_2(self):
- utils.create_test_node(deploy_interface='direct')
- for _i in range(3):
- uuid = uuidutils.generate_uuid()
- utils.create_test_node(uuid=uuid, deploy_interface='iscsi')
- self.assertEqual(
- (3, 2), self.dbapi.migrate_from_iscsi_deploy(self.context, 2))
- self.assertEqual(
- (1, 1), self.dbapi.migrate_from_iscsi_deploy(self.context, 2))
-
- def test_migrate_all(self):
- utils.create_test_node(deploy_interface='direct')
- for _i in range(3):
- uuid = uuidutils.generate_uuid()
- utils.create_test_node(uuid=uuid, deploy_interface='iscsi')
- self.assertEqual(
- (3, 3), self.dbapi.migrate_from_iscsi_deploy(self.context, 0))
-
- def test_migration_impossible(self):
- self.config(enabled_deploy_interfaces='iscsi')
- for _i in range(3):
- uuid = uuidutils.generate_uuid()
- utils.create_test_node(uuid=uuid, deploy_interface='iscsi')
- self.assertEqual(
- (0, 0), self.dbapi.migrate_from_iscsi_deploy(self.context, 0))
-
- def test_migration_impossible2(self):
- self.config(image_download_source='swift', group='agent')
- for _i in range(3):
- uuid = uuidutils.generate_uuid()
- utils.create_test_node(uuid=uuid, deploy_interface='iscsi')
- self.assertEqual(
- (0, 0), self.dbapi.migrate_from_iscsi_deploy(self.context, 0))
-
- def test_migration_impossible3(self):
- self.config(default_deploy_interface='iscsi')
- for _i in range(3):
- uuid = uuidutils.generate_uuid()
- utils.create_test_node(uuid=uuid, deploy_interface='iscsi')
- self.assertEqual(
- (0, 0), self.dbapi.migrate_from_iscsi_deploy(self.context, 0))
-
- def test_force_migration(self):
- self.config(enabled_deploy_interfaces='iscsi')
- utils.create_test_node(deploy_interface='direct')
- for _i in range(3):
- uuid = uuidutils.generate_uuid()
- utils.create_test_node(uuid=uuid, deploy_interface='iscsi')
- self.assertEqual(
- (3, 3), self.dbapi.migrate_from_iscsi_deploy(self.context, 0,
- force=True))
diff --git a/ironic/tests/unit/db/test_conductor.py b/ironic/tests/unit/db/test_conductor.py
index 1b390af23..fe4e93ed9 100644
--- a/ironic/tests/unit/db/test_conductor.py
+++ b/ironic/tests/unit/db/test_conductor.py
@@ -59,7 +59,7 @@ class DbConductorTestCase(base.DbTestCase):
def test_register_conductor_hardware_interfaces(self):
c = self._create_test_cdr()
- interfaces = ['direct', 'iscsi']
+ interfaces = ['direct', 'ansible']
self.dbapi.register_conductor_hardware_interfaces(
c.id,
[{'hardware_type': 'generic', 'interface_type': 'deploy',
@@ -74,10 +74,10 @@ class DbConductorTestCase(base.DbTestCase):
self.assertEqual('generic', ci2.hardware_type)
self.assertEqual('deploy', ci1.interface_type)
self.assertEqual('deploy', ci2.interface_type)
- self.assertEqual('direct', ci1.interface_name)
- self.assertEqual('iscsi', ci2.interface_name)
- self.assertFalse(ci1.default)
- self.assertTrue(ci2.default)
+ self.assertEqual('ansible', ci1.interface_name)
+ self.assertEqual('direct', ci2.interface_name)
+ self.assertTrue(ci1.default)
+ self.assertFalse(ci2.default)
def test_register_conductor_hardware_interfaces_duplicate(self):
c = self._create_test_cdr()
@@ -85,7 +85,7 @@ class DbConductorTestCase(base.DbTestCase):
{'hardware_type': 'generic', 'interface_type': 'deploy',
'interface_name': 'direct', 'default': False},
{'hardware_type': 'generic', 'interface_type': 'deploy',
- 'interface_name': 'iscsi', 'default': True}
+ 'interface_name': 'ansible', 'default': True}
]
self.dbapi.register_conductor_hardware_interfaces(c.id, interfaces)
ifaces = self.dbapi.list_conductor_hardware_interfaces(c.id)
@@ -100,7 +100,7 @@ class DbConductorTestCase(base.DbTestCase):
def test_unregister_conductor_hardware_interfaces(self):
c = self._create_test_cdr()
- interfaces = ['direct', 'iscsi']
+ interfaces = ['direct', 'ansible']
self.dbapi.register_conductor_hardware_interfaces(
c.id,
[{'hardware_type': 'generic', 'interface_type': 'deploy',
diff --git a/ironic/tests/unit/drivers/modules/ilo/test_boot.py b/ironic/tests/unit/drivers/modules/ilo/test_boot.py
index 0c496772e..81047956f 100644
--- a/ironic/tests/unit/drivers/modules/ilo/test_boot.py
+++ b/ironic/tests/unit/drivers/modules/ilo/test_boot.py
@@ -1387,7 +1387,7 @@ class IloUefiHttpsBootTestCase(db_base.DbTestCase):
self.config(enabled_hardware_types=['ilo5'],
enabled_boot_interfaces=['ilo-uefi-https'],
enabled_console_interfaces=['ilo'],
- enabled_deploy_interfaces=['iscsi'],
+ enabled_deploy_interfaces=['direct'],
enabled_inspect_interfaces=['ilo'],
enabled_management_interfaces=['ilo5'],
enabled_power_interfaces=['ilo'],
diff --git a/ironic/tests/unit/drivers/modules/ilo/test_management.py b/ironic/tests/unit/drivers/modules/ilo/test_management.py
index 07bb9f98b..80cb07c9f 100644
--- a/ironic/tests/unit/drivers/modules/ilo/test_management.py
+++ b/ironic/tests/unit/drivers/modules/ilo/test_management.py
@@ -1535,7 +1535,7 @@ class Ilo5ManagementTestCase(db_base.DbTestCase):
self.config(enabled_hardware_types=['ilo5'],
enabled_boot_interfaces=['ilo-virtual-media'],
enabled_console_interfaces=['ilo'],
- enabled_deploy_interfaces=['iscsi'],
+ enabled_deploy_interfaces=['direct'],
enabled_inspect_interfaces=['ilo'],
enabled_management_interfaces=['ilo5'],
enabled_power_interfaces=['ilo'],
diff --git a/ironic/tests/unit/drivers/modules/ilo/test_raid.py b/ironic/tests/unit/drivers/modules/ilo/test_raid.py
index ddb6b1d8b..fcb0314b1 100644
--- a/ironic/tests/unit/drivers/modules/ilo/test_raid.py
+++ b/ironic/tests/unit/drivers/modules/ilo/test_raid.py
@@ -53,7 +53,7 @@ class Ilo5RAIDTestCase(db_base.DbTestCase):
self.config(enabled_hardware_types=['ilo5'],
enabled_boot_interfaces=['ilo-virtual-media'],
enabled_console_interfaces=['ilo'],
- enabled_deploy_interfaces=['iscsi'],
+ enabled_deploy_interfaces=['direct'],
enabled_inspect_interfaces=['ilo'],
enabled_management_interfaces=['ilo5'],
enabled_power_interfaces=['ilo'],
diff --git a/ironic/tests/unit/drivers/modules/test_agent_client.py b/ironic/tests/unit/drivers/modules/test_agent_client.py
index 76db6d1bd..59f76aa15 100644
--- a/ironic/tests/unit/drivers/modules/test_agent_client.py
+++ b/ironic/tests/unit/drivers/modules/test_agent_client.py
@@ -464,46 +464,6 @@ class TestAgentClient(base.TestCase):
timeout=CONF.agent.command_timeout,
verify='/path/to/agent.crt')
- def test_start_iscsi_target(self):
- self.client._command = mock.MagicMock(spec_set=[])
- iqn = 'fake-iqn'
- port = agent_client.DEFAULT_IPA_PORTAL_PORT
- wipe_disk_metadata = False
- params = {'iqn': iqn, 'portal_port': port,
- 'wipe_disk_metadata': wipe_disk_metadata}
-
- self.client.start_iscsi_target(self.node, iqn)
- self.client._command.assert_called_once_with(
- node=self.node, method='iscsi.start_iscsi_target',
- params=params, wait=True)
-
- def test_start_iscsi_target_custom_port(self):
- self.client._command = mock.MagicMock(spec_set=[])
- iqn = 'fake-iqn'
- port = 3261
- wipe_disk_metadata = False
- params = {'iqn': iqn, 'portal_port': port,
- 'wipe_disk_metadata': wipe_disk_metadata}
-
- self.client.start_iscsi_target(self.node, iqn, portal_port=port)
- self.client._command.assert_called_once_with(
- node=self.node, method='iscsi.start_iscsi_target',
- params=params, wait=True)
-
- def test_start_iscsi_target_wipe_disk_metadata(self):
- self.client._command = mock.MagicMock(spec_set=[])
- iqn = 'fake-iqn'
- port = agent_client.DEFAULT_IPA_PORTAL_PORT
- wipe_disk_metadata = True
- params = {'iqn': iqn, 'portal_port': port,
- 'wipe_disk_metadata': wipe_disk_metadata}
-
- self.client.start_iscsi_target(self.node, iqn,
- wipe_disk_metadata=wipe_disk_metadata)
- self.client._command.assert_called_once_with(
- node=self.node, method='iscsi.start_iscsi_target',
- params=params, wait=True)
-
def _test_install_bootloader(self, root_uuid, efi_system_part_uuid=None,
prep_boot_part_uuid=None):
self.client._command = mock.MagicMock(spec_set=[])
diff --git a/ironic/tests/unit/drivers/modules/test_iscsi_deploy.py b/ironic/tests/unit/drivers/modules/test_iscsi_deploy.py
deleted file mode 100644
index 289e29e49..000000000
--- a/ironic/tests/unit/drivers/modules/test_iscsi_deploy.py
+++ /dev/null
@@ -1,1816 +0,0 @@
-# Copyright 2013 Hewlett-Packard Development Company, L.P.
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# 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. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-"""Test class for iSCSI deploy mechanism."""
-
-import os
-import tempfile
-import time
-import types
-from unittest import mock
-
-from ironic_lib import disk_utils
-from ironic_lib import utils as ironic_utils
-from oslo_concurrency import processutils
-from oslo_config import cfg
-from oslo_utils import fileutils
-import testtools
-
-from ironic.common import boot_devices
-from ironic.common import dhcp_factory
-from ironic.common import exception
-from ironic.common import pxe_utils
-from ironic.common import states
-from ironic.common import utils
-from ironic.conductor import task_manager
-from ironic.conductor import utils as manager_utils
-from ironic.drivers.modules import agent_base
-from ironic.drivers.modules import agent_client
-from ironic.drivers.modules import deploy_utils
-from ironic.drivers.modules import fake
-from ironic.drivers.modules import iscsi_deploy
-from ironic.drivers.modules.network import flat as flat_network
-from ironic.drivers.modules import pxe
-from ironic.drivers.modules.storage import noop as noop_storage
-from ironic.drivers import utils as driver_utils
-from ironic.tests import base as tests_base
-from ironic.tests.unit.db import base as db_base
-from ironic.tests.unit.db import utils as db_utils
-from ironic.tests.unit.objects import utils as obj_utils
-
-CONF = cfg.CONF
-
-INST_INFO_DICT = db_utils.get_test_pxe_instance_info()
-DRV_INFO_DICT = db_utils.get_test_pxe_driver_info()
-DRV_INTERNAL_INFO_DICT = db_utils.get_test_pxe_driver_internal_info()
-
-
-class IscsiDeployPrivateMethodsTestCase(db_base.DbTestCase):
-
- def setUp(self):
- super(IscsiDeployPrivateMethodsTestCase, self).setUp()
- n = {
- 'boot_interface': 'pxe',
- 'deploy_interface': 'iscsi',
- 'instance_info': INST_INFO_DICT,
- 'driver_info': DRV_INFO_DICT,
- 'driver_internal_info': DRV_INTERNAL_INFO_DICT,
- }
- self.node = obj_utils.create_test_node(self.context, **n)
-
- def test__save_disk_layout(self):
- info = dict(INST_INFO_DICT)
- info['ephemeral_gb'] = 10
- info['swap_mb'] = 0
- info['root_gb'] = 10
- info['preserve_ephemeral'] = False
- self.node.instance_info = info
-
- iscsi_deploy._save_disk_layout(self.node, info)
- self.node.refresh()
- for param in ('ephemeral_gb', 'swap_mb', 'root_gb'):
- self.assertEqual(
- info[param], self.node.driver_internal_info['instance'][param]
- )
-
- def test__get_image_dir_path(self):
- self.assertEqual(os.path.join(CONF.pxe.images_path,
- self.node.uuid),
- deploy_utils._get_image_dir_path(self.node.uuid))
-
- def test__get_image_file_path(self):
- self.assertEqual(os.path.join(CONF.pxe.images_path,
- self.node.uuid,
- 'disk'),
- deploy_utils._get_image_file_path(self.node.uuid))
-
-
-class IscsiDeployMethodsTestCase(db_base.DbTestCase):
-
- def setUp(self):
- super(IscsiDeployMethodsTestCase, self).setUp()
- instance_info = dict(INST_INFO_DICT)
- instance_info['deploy_key'] = 'fake-56789'
- n = {
- 'boot_interface': 'pxe',
- 'deploy_interface': 'iscsi',
- 'instance_info': instance_info,
- 'driver_info': DRV_INFO_DICT,
- 'driver_internal_info': DRV_INTERNAL_INFO_DICT,
- }
- self.node = obj_utils.create_test_node(self.context, **n)
-
- @mock.patch.object(disk_utils, 'get_image_mb', autospec=True)
- def test_check_image_size(self, get_image_mb_mock):
- get_image_mb_mock.return_value = 1000
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- task.node.instance_info['root_gb'] = 1
- iscsi_deploy.check_image_size(task)
- get_image_mb_mock.assert_called_once_with(
- deploy_utils._get_image_file_path(task.node.uuid))
-
- @mock.patch.object(disk_utils, 'get_image_mb', autospec=True)
- def test_check_image_size_whole_disk_image(self, get_image_mb_mock):
- get_image_mb_mock.return_value = 1025
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- task.node.instance_info['root_gb'] = 1
- task.node.driver_internal_info['is_whole_disk_image'] = True
- # No error for whole disk images
- iscsi_deploy.check_image_size(task)
- self.assertFalse(get_image_mb_mock.called)
-
- @mock.patch.object(disk_utils, 'get_image_mb', autospec=True)
- def test_check_image_size_whole_disk_image_no_root(self,
- get_image_mb_mock):
- get_image_mb_mock.return_value = 1025
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- del task.node.instance_info['root_gb']
- task.node.driver_internal_info['is_whole_disk_image'] = True
- # No error for whole disk images
- iscsi_deploy.check_image_size(task)
- self.assertFalse(get_image_mb_mock.called)
-
- @mock.patch.object(disk_utils, 'get_image_mb', autospec=True)
- def test_check_image_size_fails(self, get_image_mb_mock):
- get_image_mb_mock.return_value = 1025
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- task.node.instance_info['root_gb'] = 1
- self.assertRaises(exception.InstanceDeployFailure,
- iscsi_deploy.check_image_size,
- task)
- get_image_mb_mock.assert_called_once_with(
- deploy_utils._get_image_file_path(task.node.uuid))
-
- @mock.patch.object(deploy_utils, 'fetch_images', autospec=True)
- def test_cache_instance_images_master_path(self, mock_fetch_image):
- temp_dir = tempfile.mkdtemp()
- self.config(images_path=temp_dir, group='pxe')
- self.config(instance_master_path=os.path.join(temp_dir,
- 'instance_master_path'),
- group='pxe')
- fileutils.ensure_tree(CONF.pxe.instance_master_path)
-
- (uuid, image_path) = deploy_utils.cache_instance_image(None, self.node)
- mock_fetch_image.assert_called_once_with(None,
- mock.ANY,
- [(uuid, image_path)], True)
- self.assertEqual('glance://image_uuid', uuid)
- self.assertEqual(os.path.join(temp_dir,
- self.node.uuid,
- 'disk'),
- image_path)
-
- @mock.patch.object(ironic_utils, 'unlink_without_raise', autospec=True)
- @mock.patch.object(utils, 'rmtree_without_raise', autospec=True)
- @mock.patch.object(deploy_utils, 'InstanceImageCache', autospec=True)
- def test_destroy_images(self, mock_cache, mock_rmtree, mock_unlink):
- self.config(images_path='/path', group='pxe')
-
- deploy_utils.destroy_images('uuid')
-
- mock_cache.return_value.clean_up.assert_called_once_with()
- mock_unlink.assert_called_once_with('/path/uuid/disk')
- mock_rmtree.assert_called_once_with('/path/uuid')
-
- @mock.patch.object(driver_utils, 'collect_ramdisk_logs', autospec=True)
- @mock.patch.object(iscsi_deploy, '_save_disk_layout', autospec=True)
- @mock.patch.object(deploy_utils, 'InstanceImageCache', autospec=True)
- @mock.patch.object(manager_utils, 'node_power_action', autospec=True)
- @mock.patch.object(iscsi_deploy, 'deploy_partition_image', autospec=True)
- def test_continue_deploy_fail(
- self, deploy_mock, power_mock, mock_image_cache, mock_disk_layout,
- mock_collect_logs):
- kwargs = {'address': '123456', 'iqn': 'aaa-bbb', 'conv_flags': None}
- deploy_mock.side_effect = exception.InstanceDeployFailure(
- "test deploy error")
- self.node.provision_state = states.DEPLOYWAIT
- self.node.target_provision_state = states.ACTIVE
- self.node.save()
-
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- params = iscsi_deploy.get_deploy_info(task.node, **kwargs)
- # Ironic exceptions are preserved as they are
- self.assertRaisesRegex(exception.InstanceDeployFailure,
- '^test deploy error$',
- iscsi_deploy.continue_deploy,
- task, **kwargs)
- self.assertEqual(states.DEPLOYFAIL, task.node.provision_state)
- self.assertEqual(states.ACTIVE, task.node.target_provision_state)
- self.assertIsNotNone(task.node.last_error)
- deploy_mock.assert_called_once_with(**params)
- power_mock.assert_called_once_with(task, states.POWER_OFF)
- mock_image_cache.assert_called_once_with()
- mock_image_cache.return_value.clean_up.assert_called_once_with()
- self.assertFalse(mock_disk_layout.called)
- mock_collect_logs.assert_called_once_with(task.node)
-
- @mock.patch.object(driver_utils, 'collect_ramdisk_logs', autospec=True)
- @mock.patch.object(iscsi_deploy, '_save_disk_layout', autospec=True)
- @mock.patch.object(deploy_utils, 'InstanceImageCache', autospec=True)
- @mock.patch.object(manager_utils, 'node_power_action', autospec=True)
- @mock.patch.object(iscsi_deploy, 'deploy_partition_image', autospec=True)
- def test_continue_deploy_unexpected_fail(
- self, deploy_mock, power_mock, mock_image_cache, mock_disk_layout,
- mock_collect_logs):
- kwargs = {'address': '123456', 'iqn': 'aaa-bbb'}
- deploy_mock.side_effect = KeyError('boom')
- self.node.provision_state = states.DEPLOYWAIT
- self.node.target_provision_state = states.ACTIVE
- self.node.save()
-
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- params = iscsi_deploy.get_deploy_info(task.node, **kwargs)
- self.assertRaisesRegex(exception.InstanceDeployFailure,
- "Deploy failed.*Error: 'boom'",
- iscsi_deploy.continue_deploy,
- task, **kwargs)
- self.assertEqual(states.DEPLOYFAIL, task.node.provision_state)
- self.assertEqual(states.ACTIVE, task.node.target_provision_state)
- self.assertIsNotNone(task.node.last_error)
- deploy_mock.assert_called_once_with(**params)
- power_mock.assert_called_once_with(task, states.POWER_OFF)
- mock_image_cache.assert_called_once_with()
- mock_image_cache.return_value.clean_up.assert_called_once_with()
- self.assertFalse(mock_disk_layout.called)
- mock_collect_logs.assert_called_once_with(task.node)
-
- @mock.patch.object(driver_utils, 'collect_ramdisk_logs', autospec=True)
- @mock.patch.object(iscsi_deploy, '_save_disk_layout', autospec=True)
- @mock.patch.object(deploy_utils, 'InstanceImageCache', autospec=True)
- @mock.patch.object(manager_utils, 'node_power_action', autospec=True)
- @mock.patch.object(iscsi_deploy, 'deploy_partition_image', autospec=True)
- def test_continue_deploy_fail_no_root_uuid_or_disk_id(
- self, deploy_mock, power_mock, mock_image_cache, mock_disk_layout,
- mock_collect_logs):
- kwargs = {'address': '123456', 'iqn': 'aaa-bbb'}
- deploy_mock.return_value = {}
- self.node.provision_state = states.DEPLOYWAIT
- self.node.target_provision_state = states.ACTIVE
- self.node.save()
-
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- params = iscsi_deploy.get_deploy_info(task.node, **kwargs)
- self.assertRaises(exception.InstanceDeployFailure,
- iscsi_deploy.continue_deploy,
- task, **kwargs)
- self.assertEqual(states.DEPLOYFAIL, task.node.provision_state)
- self.assertEqual(states.ACTIVE, task.node.target_provision_state)
- self.assertIsNotNone(task.node.last_error)
- deploy_mock.assert_called_once_with(**params)
- power_mock.assert_called_once_with(task, states.POWER_OFF)
- mock_image_cache.assert_called_once_with()
- mock_image_cache.return_value.clean_up.assert_called_once_with()
- self.assertFalse(mock_disk_layout.called)
- mock_collect_logs.assert_called_once_with(task.node)
-
- @mock.patch.object(driver_utils, 'collect_ramdisk_logs', autospec=True)
- @mock.patch.object(iscsi_deploy, '_save_disk_layout', autospec=True)
- @mock.patch.object(deploy_utils, 'InstanceImageCache', autospec=True)
- @mock.patch.object(manager_utils, 'node_power_action', autospec=True)
- @mock.patch.object(iscsi_deploy, 'deploy_partition_image', autospec=True)
- def test_continue_deploy_fail_empty_root_uuid(
- self, deploy_mock, power_mock, mock_image_cache,
- mock_disk_layout, mock_collect_logs):
- kwargs = {'address': '123456', 'iqn': 'aaa-bbb'}
- deploy_mock.return_value = {'root uuid': ''}
- self.node.provision_state = states.DEPLOYWAIT
- self.node.target_provision_state = states.ACTIVE
- self.node.save()
-
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- params = iscsi_deploy.get_deploy_info(task.node, **kwargs)
- self.assertRaises(exception.InstanceDeployFailure,
- iscsi_deploy.continue_deploy,
- task, **kwargs)
- self.assertEqual(states.DEPLOYFAIL, task.node.provision_state)
- self.assertEqual(states.ACTIVE, task.node.target_provision_state)
- self.assertIsNotNone(task.node.last_error)
- deploy_mock.assert_called_once_with(**params)
- power_mock.assert_called_once_with(task, states.POWER_OFF)
- mock_image_cache.assert_called_once_with()
- mock_image_cache.return_value.clean_up.assert_called_once_with()
- self.assertFalse(mock_disk_layout.called)
- mock_collect_logs.assert_called_once_with(task.node)
-
- @mock.patch.object(iscsi_deploy, '_save_disk_layout', autospec=True)
- @mock.patch.object(iscsi_deploy, 'LOG', autospec=True)
- @mock.patch.object(iscsi_deploy, 'get_deploy_info', autospec=True)
- @mock.patch.object(deploy_utils, 'InstanceImageCache', autospec=True)
- @mock.patch.object(manager_utils, 'node_power_action', autospec=True)
- @mock.patch.object(iscsi_deploy, 'deploy_partition_image', autospec=True)
- def test_continue_deploy(self, deploy_mock, power_mock, mock_image_cache,
- mock_deploy_info, mock_log, mock_disk_layout):
- kwargs = {'address': '123456', 'iqn': 'aaa-bbb'}
- self.node.provision_state = states.DEPLOYWAIT
- self.node.target_provision_state = states.ACTIVE
- self.node.save()
-
- mock_deploy_info.return_value = {
- 'address': '123456',
- 'boot_option': 'netboot',
- 'configdrive': "I've got the power",
- 'ephemeral_format': None,
- 'ephemeral_mb': 0,
- 'image_path': (u'/var/lib/ironic/images/1be26c0b-03f2-4d2e-ae87-'
- u'c02d7f33c123/disk'),
- 'iqn': 'aaa-bbb',
- 'lun': '1',
- 'node_uuid': u'1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
- 'port': '3260',
- 'preserve_ephemeral': True,
- 'root_mb': 102400,
- 'swap_mb': 0,
- }
- log_params = mock_deploy_info.return_value.copy()
- # Make sure we don't log the full content of the configdrive
- log_params['configdrive'] = '***'
- expected_dict = {
- 'node': self.node.uuid,
- 'params': log_params,
- }
- deployment_uuids = {'root uuid': '12345678-87654321'}
- deploy_mock.return_value = deployment_uuids
-
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- mock_log.isEnabledFor.return_value = True
- retval = iscsi_deploy.continue_deploy(task, **kwargs)
- mock_log.debug.assert_called_once_with(
- mock.ANY, expected_dict)
- self.assertEqual(states.DEPLOYWAIT, task.node.provision_state)
- self.assertEqual(states.ACTIVE, task.node.target_provision_state)
- self.assertIsNone(task.node.last_error)
- mock_image_cache.assert_called_once_with()
- mock_image_cache.return_value.clean_up.assert_called_once_with()
- self.assertEqual(deployment_uuids, retval)
- mock_disk_layout.assert_called_once_with(task.node, mock.ANY)
-
- @mock.patch.object(iscsi_deploy, 'LOG', autospec=True)
- @mock.patch.object(iscsi_deploy, 'get_deploy_info', autospec=True)
- @mock.patch.object(deploy_utils, 'InstanceImageCache', autospec=True)
- @mock.patch.object(manager_utils, 'node_power_action', autospec=True)
- @mock.patch.object(iscsi_deploy, 'deploy_disk_image', autospec=True)
- def test_continue_deploy_whole_disk_image(
- self, deploy_mock, power_mock, mock_image_cache, mock_deploy_info,
- mock_log):
- kwargs = {'address': '123456', 'iqn': 'aaa-bbb'}
- self.node.provision_state = states.DEPLOYWAIT
- self.node.target_provision_state = states.ACTIVE
- self.node.save()
-
- mock_deploy_info.return_value = {
- 'address': '123456',
- 'image_path': (u'/var/lib/ironic/images/1be26c0b-03f2-4d2e-ae87-'
- u'c02d7f33c123/disk'),
- 'iqn': 'aaa-bbb',
- 'lun': '1',
- 'node_uuid': u'1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
- 'port': '3260',
- }
- log_params = mock_deploy_info.return_value.copy()
- expected_dict = {
- 'node': self.node.uuid,
- 'params': log_params,
- }
- deployment_uuids = {'disk identifier': '87654321'}
- deploy_mock.return_value = deployment_uuids
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- task.node.driver_internal_info['is_whole_disk_image'] = True
- mock_log.isEnabledFor.return_value = True
- retval = iscsi_deploy.continue_deploy(task, **kwargs)
- mock_log.debug.assert_called_once_with(
- mock.ANY, expected_dict)
- self.assertEqual(states.DEPLOYWAIT, task.node.provision_state)
- self.assertEqual(states.ACTIVE, task.node.target_provision_state)
- self.assertIsNone(task.node.last_error)
- mock_image_cache.assert_called_once_with()
- mock_image_cache.return_value.clean_up.assert_called_once_with()
- self.assertEqual(deployment_uuids, retval)
-
- def _test_get_deploy_info(self, extra_instance_info=None):
- if extra_instance_info is None:
- extra_instance_info = {}
-
- instance_info = self.node.instance_info
- instance_info.update(extra_instance_info)
- self.node.instance_info = instance_info
- kwargs = {'address': '1.1.1.1', 'iqn': 'target-iqn'}
- ret_val = iscsi_deploy.get_deploy_info(self.node, **kwargs)
- self.assertEqual('1.1.1.1', ret_val['address'])
- self.assertEqual('target-iqn', ret_val['iqn'])
- return ret_val
-
- def test_get_deploy_info_boot_option_default(self):
- ret_val = self._test_get_deploy_info()
- self.assertEqual('local', ret_val['boot_option'])
-
- def test_get_deploy_info_netboot_specified(self):
- capabilities = {'capabilities': {'boot_option': 'netboot'}}
- ret_val = self._test_get_deploy_info(extra_instance_info=capabilities)
- self.assertEqual('netboot', ret_val['boot_option'])
-
- def test_get_deploy_info_localboot(self):
- capabilities = {'capabilities': {'boot_option': 'local'}}
- ret_val = self._test_get_deploy_info(extra_instance_info=capabilities)
- self.assertEqual('local', ret_val['boot_option'])
-
- def test_get_deploy_info_cpu_arch(self):
- ret_val = self._test_get_deploy_info()
- self.assertEqual('x86_64', ret_val['cpu_arch'])
-
- def test_get_deploy_info_cpu_arch_none(self):
- self.node.properties['cpu_arch'] = None
- ret_val = self._test_get_deploy_info()
- self.assertNotIn('cpu_arch', ret_val)
-
- def test_get_deploy_info_disk_label(self):
- capabilities = {'capabilities': {'disk_label': 'msdos'}}
- ret_val = self._test_get_deploy_info(extra_instance_info=capabilities)
- self.assertEqual('msdos', ret_val['disk_label'])
-
- def test_get_deploy_info_not_specified(self):
- ret_val = self._test_get_deploy_info()
- self.assertNotIn('disk_label', ret_val)
-
- def test_get_deploy_info_portal_port(self):
- self.config(portal_port=3266, group='iscsi')
- ret_val = self._test_get_deploy_info()
- self.assertEqual(3266, ret_val['port'])
-
- def test_get_deploy_info_whole_disk_image(self):
- instance_info = self.node.instance_info
- instance_info['configdrive'] = 'My configdrive'
- self.node.instance_info = instance_info
- self.node.driver_internal_info['is_whole_disk_image'] = True
- kwargs = {'address': '1.1.1.1', 'iqn': 'target-iqn'}
- ret_val = iscsi_deploy.get_deploy_info(self.node, **kwargs)
- self.assertEqual('1.1.1.1', ret_val['address'])
- self.assertEqual('target-iqn', ret_val['iqn'])
- self.assertEqual('My configdrive', ret_val['configdrive'])
-
- def test_get_deploy_info_whole_disk_image_no_root(self):
- instance_info = self.node.instance_info
- instance_info['configdrive'] = 'My configdrive'
- del instance_info['root_gb']
- self.node.instance_info = instance_info
- self.node.driver_internal_info['is_whole_disk_image'] = True
- kwargs = {'address': '1.1.1.1', 'iqn': 'target-iqn'}
- ret_val = iscsi_deploy.get_deploy_info(self.node, **kwargs)
- self.assertEqual('1.1.1.1', ret_val['address'])
- self.assertEqual('target-iqn', ret_val['iqn'])
- self.assertEqual('My configdrive', ret_val['configdrive'])
-
- @mock.patch.object(iscsi_deploy, 'continue_deploy', autospec=True)
- def test_do_agent_iscsi_deploy_okay(self, continue_deploy_mock):
- agent_client_mock = mock.MagicMock(spec_set=agent_client.AgentClient)
- agent_client_mock.start_iscsi_target.return_value = {
- 'command_status': 'SUCCESS', 'command_error': None}
- driver_internal_info = {'agent_url': 'http://1.2.3.4:1234'}
- self.node.driver_internal_info = driver_internal_info
- self.node.save()
- deployment_uuids = {'root uuid': 'some-root-uuid'}
- continue_deploy_mock.return_value = deployment_uuids
- expected_iqn = 'iqn.2008-10.org.openstack:%s' % self.node.uuid
-
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- ret_val = iscsi_deploy.do_agent_iscsi_deploy(
- task, agent_client_mock)
- agent_client_mock.start_iscsi_target.assert_called_once_with(
- task.node, expected_iqn, 3260, wipe_disk_metadata=True)
- continue_deploy_mock.assert_called_once_with(
- task, iqn=expected_iqn, address='1.2.3.4', conv_flags=None)
- self.assertEqual(
- 'some-root-uuid',
- task.node.driver_internal_info['root_uuid_or_disk_id'])
- self.assertEqual(ret_val, deployment_uuids)
-
- @mock.patch.object(iscsi_deploy, 'continue_deploy', autospec=True)
- def test_do_agent_iscsi_deploy_preserve_ephemeral(self,
- continue_deploy_mock):
- """Ensure the disk is not wiped if preserve_ephemeral is True."""
- agent_client_mock = mock.MagicMock(spec_set=agent_client.AgentClient)
- agent_client_mock.start_iscsi_target.return_value = {
- 'command_status': 'SUCCESS', 'command_error': None}
- driver_internal_info = {
- 'agent_url': 'http://1.2.3.4:1234'}
- self.node.driver_internal_info = driver_internal_info
- self.node.save()
- deployment_uuids = {'root uuid': 'some-root-uuid'}
- continue_deploy_mock.return_value = deployment_uuids
- expected_iqn = 'iqn.2008-10.org.openstack:%s' % self.node.uuid
-
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- task.node.instance_info['preserve_ephemeral'] = True
- iscsi_deploy.do_agent_iscsi_deploy(
- task, agent_client_mock)
- agent_client_mock.start_iscsi_target.assert_called_once_with(
- task.node, expected_iqn, 3260, wipe_disk_metadata=False)
-
- @mock.patch.object(driver_utils, 'collect_ramdisk_logs', autospec=True)
- def test_do_agent_iscsi_deploy_start_iscsi_failure(
- self, mock_collect_logs):
- agent_client_mock = mock.MagicMock(spec_set=agent_client.AgentClient)
- agent_client_mock.start_iscsi_target.return_value = {
- 'command_status': 'FAILED', 'command_error': 'booom'}
- self.node.provision_state = states.DEPLOYING
- self.node.target_provision_state = states.ACTIVE
- self.node.save()
- expected_iqn = 'iqn.2008-10.org.openstack:%s' % self.node.uuid
-
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- self.assertRaises(exception.InstanceDeployFailure,
- iscsi_deploy.do_agent_iscsi_deploy,
- task, agent_client_mock)
- agent_client_mock.start_iscsi_target.assert_called_once_with(
- task.node, expected_iqn, 3260, wipe_disk_metadata=True)
- self.node.refresh()
- self.assertEqual(states.DEPLOYFAIL, self.node.provision_state)
- self.assertEqual(states.ACTIVE, self.node.target_provision_state)
- self.assertIsNotNone(self.node.last_error)
- mock_collect_logs.assert_called_once_with(task.node)
-
- @mock.patch('ironic.drivers.modules.deploy_utils.get_ironic_api_url',
- autospec=True)
- def test_validate_good_api_url(self, mock_get_url):
- mock_get_url.return_value = 'http://127.0.0.1:1234'
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- iscsi_deploy.validate(task)
- mock_get_url.assert_called_once_with()
-
- @mock.patch('ironic.drivers.modules.deploy_utils.get_ironic_api_url',
- autospec=True)
- def test_validate_fail_no_api_url(self, mock_get_url):
- mock_get_url.side_effect = exception.InvalidParameterValue('Ham!')
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- self.assertRaises(exception.InvalidParameterValue,
- iscsi_deploy.validate, task)
- mock_get_url.assert_called_once_with()
-
- @mock.patch('ironic.drivers.modules.deploy_utils.get_ironic_api_url',
- autospec=True)
- def test_validate_invalid_root_device_hints(self, mock_get_url):
- mock_get_url.return_value = 'http://spam.ham/baremetal'
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- task.node.properties['root_device'] = {'size': 'not-int'}
- self.assertRaises(exception.InvalidParameterValue,
- iscsi_deploy.validate, task)
-
- @mock.patch('ironic.drivers.modules.deploy_utils.get_ironic_api_url',
- autospec=True)
- def test_validate_invalid_root_device_hints_iinfo(self, mock_get_url):
- mock_get_url.return_value = 'http://spam.ham/baremetal'
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- task.node.properties['root_device'] = {'size': 42}
- task.node.instance_info['root_device'] = {'size': 'not-int'}
- self.assertRaises(exception.InvalidParameterValue,
- iscsi_deploy.validate, task)
-
-
-class ISCSIDeployTestCase(db_base.DbTestCase):
-
- def setUp(self):
- super(ISCSIDeployTestCase, self).setUp()
- # NOTE(TheJulia): We explicitly set the noop storage interface as the
- # default below for deployment tests in order to raise any change
- # in the default which could be a breaking behavior change
- # as the storage interface is explicitly an "opt-in" interface.
- self.node = obj_utils.create_test_node(
- self.context, boot_interface='pxe', deploy_interface='iscsi',
- instance_info=INST_INFO_DICT,
- driver_info=DRV_INFO_DICT,
- driver_internal_info=DRV_INTERNAL_INFO_DICT,
- storage_interface='noop',
- )
- self.node.driver_internal_info['agent_url'] = 'http://1.2.3.4:1234'
- dhcp_factory.DHCPFactory._dhcp_provider = None
- # Memory checks shoudn't apply here as they will lead to
- # false positives for unit testing in CI.
- self.config(minimum_memory_warning_only=True)
-
- def test_get_properties(self):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- props = task.driver.deploy.get_properties()
- self.assertEqual({'agent_verify_ca', 'deploy_forces_oob_reboot'},
- set(props))
-
- @mock.patch.object(iscsi_deploy, 'validate', autospec=True)
- @mock.patch.object(deploy_utils, 'validate_capabilities', autospec=True)
- @mock.patch.object(pxe.PXEBoot, 'validate', autospec=True)
- def test_validate(self, pxe_validate_mock,
- validate_capabilities_mock, validate_mock):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
-
- task.driver.deploy.validate(task)
-
- pxe_validate_mock.assert_called_once_with(task.driver.boot, task)
- validate_capabilities_mock.assert_called_once_with(task.node)
- validate_mock.assert_called_once_with(task)
-
- @mock.patch.object(noop_storage.NoopStorage, 'should_write_image',
- autospec=True)
- @mock.patch.object(iscsi_deploy, 'validate', autospec=True)
- @mock.patch.object(deploy_utils, 'validate_capabilities', autospec=True)
- @mock.patch.object(pxe.PXEBoot, 'validate', autospec=True)
- def test_validate_storage_should_write_image_false(
- self, pxe_validate_mock,
- validate_capabilities_mock, validate_mock,
- should_write_image_mock):
- should_write_image_mock.return_value = False
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
-
- task.driver.deploy.validate(task)
-
- pxe_validate_mock.assert_called_once_with(task.driver.boot, task)
- validate_capabilities_mock.assert_called_once_with(task.node)
- self.assertFalse(validate_mock.called)
- should_write_image_mock.assert_called_once_with(
- task.driver.storage, task)
-
- @mock.patch.object(noop_storage.NoopStorage, 'attach_volumes',
- autospec=True)
- @mock.patch.object(deploy_utils, 'populate_storage_driver_internal_info',
- autospec=True)
- @mock.patch.object(flat_network.FlatNetwork, 'add_provisioning_network',
- spec_set=True, autospec=True)
- @mock.patch.object(pxe.PXEBoot, 'prepare_instance', autospec=True)
- def test_prepare_node_active(self, prepare_instance_mock,
- add_provisioning_net_mock,
- storage_driver_info_mock,
- storage_attach_volumes_mock):
- with task_manager.acquire(self.context, self.node.uuid) as task:
- task.node.provision_state = states.ACTIVE
-
- task.driver.deploy.prepare(task)
-
- prepare_instance_mock.assert_called_once_with(
- task.driver.boot, task)
- self.assertEqual(0, add_provisioning_net_mock.call_count)
- storage_driver_info_mock.assert_called_once_with(task)
- self.assertFalse(storage_attach_volumes_mock.called)
-
- @mock.patch.object(flat_network.FlatNetwork, 'add_provisioning_network',
- spec_set=True, autospec=True)
- @mock.patch.object(pxe.PXEBoot, 'prepare_instance', autospec=True)
- def test_prepare_node_adopting(self, prepare_instance_mock,
- add_provisioning_net_mock):
- with task_manager.acquire(self.context, self.node.uuid) as task:
- task.node.provision_state = states.ADOPTING
-
- task.driver.deploy.prepare(task)
-
- prepare_instance_mock.assert_called_once_with(
- task.driver.boot, task)
- self.assertEqual(0, add_provisioning_net_mock.call_count)
-
- @mock.patch.object(noop_storage.NoopStorage, 'attach_volumes',
- autospec=True)
- @mock.patch.object(deploy_utils, 'populate_storage_driver_internal_info',
- autospec=True)
- @mock.patch.object(deploy_utils, 'build_agent_options', autospec=True)
- @mock.patch.object(pxe.PXEBoot, 'prepare_ramdisk', autospec=True)
- @mock.patch.object(flat_network.FlatNetwork, 'add_provisioning_network',
- spec_set=True, autospec=True)
- @mock.patch.object(flat_network.FlatNetwork,
- 'unconfigure_tenant_networks',
- spec_set=True, autospec=True)
- def test_prepare_node_deploying(
- self, unconfigure_tenant_net_mock, add_provisioning_net_mock,
- mock_prepare_ramdisk, mock_agent_options,
- storage_driver_info_mock, storage_attach_volumes_mock):
- mock_agent_options.return_value = {'c': 'd'}
- with task_manager.acquire(self.context, self.node.uuid) as task:
- task.node.provision_state = states.DEPLOYING
-
- task.driver.deploy.prepare(task)
-
- mock_agent_options.assert_called_once_with(task.node)
- mock_prepare_ramdisk.assert_called_once_with(
- task.driver.boot, task, {'c': 'd'})
- add_provisioning_net_mock.assert_called_once_with(mock.ANY, task)
- unconfigure_tenant_net_mock.assert_called_once_with(mock.ANY, task)
- storage_driver_info_mock.assert_called_once_with(task)
- storage_attach_volumes_mock.assert_called_once_with(
- task.driver.storage, task)
-
- @mock.patch.object(noop_storage.NoopStorage, 'should_write_image',
- autospec=True)
- @mock.patch.object(noop_storage.NoopStorage, 'attach_volumes',
- autospec=True)
- @mock.patch.object(deploy_utils, 'populate_storage_driver_internal_info',
- autospec=True)
- @mock.patch.object(deploy_utils, 'build_agent_options', autospec=True)
- @mock.patch.object(pxe.PXEBoot, 'prepare_ramdisk', autospec=True)
- @mock.patch.object(flat_network.FlatNetwork, 'add_provisioning_network',
- spec_set=True, autospec=True)
- @mock.patch.object(flat_network.FlatNetwork,
- 'unconfigure_tenant_networks',
- spec_set=True, autospec=True)
- def test_prepare_node_deploying_storage_should_write_false(
- self, unconfigure_tenant_net_mock, add_provisioning_net_mock,
- mock_prepare_ramdisk, mock_agent_options,
- storage_driver_info_mock, storage_attach_volumes_mock,
- storage_should_write_mock):
- storage_should_write_mock.return_value = False
- mock_agent_options.return_value = {'c': 'd'}
- with task_manager.acquire(self.context, self.node.uuid) as task:
- task.node.provision_state = states.DEPLOYING
-
- task.driver.deploy.prepare(task)
-
- self.assertFalse(mock_agent_options.called)
- self.assertFalse(mock_prepare_ramdisk.called)
- self.assertFalse(add_provisioning_net_mock.called)
- self.assertFalse(unconfigure_tenant_net_mock.called)
- storage_driver_info_mock.assert_called_once_with(task)
- storage_attach_volumes_mock.assert_called_once_with(
- task.driver.storage, task)
- self.assertEqual(2, storage_should_write_mock.call_count)
-
- @mock.patch('ironic.conductor.utils.is_fast_track', autospec=True)
- @mock.patch.object(noop_storage.NoopStorage, 'attach_volumes',
- autospec=True)
- @mock.patch.object(deploy_utils, 'populate_storage_driver_internal_info',
- autospec=True)
- @mock.patch.object(pxe.PXEBoot, 'prepare_ramdisk', autospec=True)
- @mock.patch.object(deploy_utils, 'build_agent_options',
- autospec=True)
- @mock.patch.object(deploy_utils, 'build_instance_info_for_deploy',
- autospec=True)
- @mock.patch.object(flat_network.FlatNetwork, 'add_provisioning_network',
- spec_set=True, autospec=True)
- @mock.patch.object(flat_network.FlatNetwork,
- 'unconfigure_tenant_networks',
- spec_set=True, autospec=True)
- @mock.patch.object(flat_network.FlatNetwork, 'validate',
- spec_set=True, autospec=True)
- def test_prepare_fast_track(
- self, validate_net_mock,
- unconfigure_tenant_net_mock, add_provisioning_net_mock,
- build_instance_info_mock, build_options_mock,
- pxe_prepare_ramdisk_mock, storage_driver_info_mock,
- storage_attach_volumes_mock, is_fast_track_mock):
- # TODO(TheJulia): We should revisit this test. Smartnic
- # support didn't wire in tightly on testing for power in
- # these tests, and largely fast_track impacts power operations.
- node = self.node
- node.network_interface = 'flat'
- node.save()
- is_fast_track_mock.return_value = True
- with task_manager.acquire(
- self.context, self.node['uuid'], shared=False) as task:
- task.node.provision_state = states.DEPLOYING
- build_options_mock.return_value = {'a': 'b'}
- task.driver.deploy.prepare(task)
- storage_driver_info_mock.assert_called_once_with(task)
- # NOTE: Validate is the primary difference between agent/iscsi
- self.assertFalse(validate_net_mock.called)
- add_provisioning_net_mock.assert_called_once_with(mock.ANY, task)
- unconfigure_tenant_net_mock.assert_called_once_with(mock.ANY, task)
- self.assertTrue(storage_attach_volumes_mock.called)
- self.assertFalse(build_instance_info_mock.called)
- # TODO(TheJulia): We should likely consider executing the
- # next two methods at some point in order to facilitate
- # continuity. While not explicitly required for this feature
- # to work, reboots as part of deployment would need the ramdisk
- # present and ready.
- self.assertFalse(build_options_mock.called)
- self.assertFalse(pxe_prepare_ramdisk_mock.called)
-
- @mock.patch.object(manager_utils, 'node_power_action', autospec=True)
- @mock.patch.object(iscsi_deploy, 'check_image_size', autospec=True)
- @mock.patch.object(deploy_utils, 'cache_instance_image', autospec=True)
- def test_deploy(self, mock_cache_instance_image,
- mock_check_image_size, mock_node_power_action):
- with task_manager.acquire(self.context,
- self.node.uuid, shared=False) as task:
- state = task.driver.deploy.deploy(task)
- self.assertEqual(state, states.DEPLOYWAIT)
- mock_cache_instance_image.assert_called_once_with(
- self.context, task.node)
- mock_check_image_size.assert_called_once_with(task)
- mock_node_power_action.assert_called_once_with(task, states.REBOOT)
-
- @mock.patch.object(manager_utils, 'node_power_action', autospec=True)
- @mock.patch.object(iscsi_deploy, 'check_image_size', autospec=True)
- @mock.patch.object(deploy_utils, 'cache_instance_image', autospec=True)
- def test_deploy_with_deployment_reboot(self, mock_cache_instance_image,
- mock_check_image_size,
- mock_node_power_action):
- driver_internal_info = self.node.driver_internal_info
- driver_internal_info['deployment_reboot'] = True
- self.node.driver_internal_info = driver_internal_info
- self.node.save()
- with task_manager.acquire(self.context,
- self.node.uuid, shared=False) as task:
- state = task.driver.deploy.deploy(task)
- self.assertEqual(state, states.DEPLOYWAIT)
- mock_cache_instance_image.assert_called_once_with(
- self.context, task.node)
- mock_check_image_size.assert_called_once_with(task)
- self.assertFalse(mock_node_power_action.called)
- self.assertNotIn(
- 'deployment_reboot', task.node.driver_internal_info)
-
- @mock.patch.object(manager_utils, 'node_power_action', autospec=True)
- @mock.patch.object(noop_storage.NoopStorage, 'should_write_image',
- autospec=True)
- def test_deploy_storage_should_write_image_false(
- self, mock_write, mock_node_power_action):
- mock_write.return_value = False
- self.node.provision_state = states.DEPLOYING
- self.node.deploy_step = {
- 'step': 'deploy', 'priority': 50, 'interface': 'deploy'}
- self.node.save()
- with task_manager.acquire(
- self.context, self.node.uuid, shared=False) as task:
- ret = task.driver.deploy.deploy(task)
- self.assertIsNone(ret)
- self.assertFalse(mock_node_power_action.called)
-
- @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'refresh_steps',
- autospec=True)
- @mock.patch.object(iscsi_deploy, 'check_image_size', autospec=True)
- @mock.patch.object(deploy_utils, 'cache_instance_image', autospec=True)
- @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'write_image',
- autospec=True)
- @mock.patch('ironic.conductor.utils.is_fast_track', autospec=True)
- @mock.patch.object(pxe.PXEBoot, 'prepare_instance', autospec=True)
- @mock.patch('ironic.conductor.utils.node_power_action', autospec=True)
- def test_deploy_fast_track(self, power_mock, mock_pxe_instance,
- mock_is_fast_track, write_image_mock,
- cache_image_mock, check_image_size_mock,
- refresh_mock):
- mock_is_fast_track.return_value = True
- self.node.target_provision_state = states.ACTIVE
- self.node.provision_state = states.DEPLOYING
- i_info = self.node.driver_internal_info
- i_info['agent_url'] = 'http://1.2.3.4:1234'
- self.node.driver_internal_info = i_info
- self.node.save()
- with task_manager.acquire(
- self.context, self.node['uuid'], shared=False) as task:
- result = task.driver.deploy.deploy(task)
- self.assertIsNone(result)
- self.assertFalse(power_mock.called)
- self.assertFalse(mock_pxe_instance.called)
- task.node.refresh()
- self.assertEqual(states.DEPLOYING, task.node.provision_state)
- self.assertEqual(states.ACTIVE,
- task.node.target_provision_state)
- cache_image_mock.assert_called_with(mock.ANY, task.node)
- check_image_size_mock.assert_called_with(task)
- self.assertFalse(write_image_mock.called)
- refresh_mock.assert_called_once_with(task.driver.deploy,
- task, 'deploy')
-
- @mock.patch.object(noop_storage.NoopStorage, 'detach_volumes',
- autospec=True)
- @mock.patch.object(flat_network.FlatNetwork,
- 'remove_provisioning_network',
- spec_set=True, autospec=True)
- @mock.patch.object(flat_network.FlatNetwork,
- 'unconfigure_tenant_networks',
- spec_set=True, autospec=True)
- @mock.patch.object(manager_utils, 'node_power_action', autospec=True)
- def test_tear_down(self, node_power_action_mock,
- unconfigure_tenant_nets_mock,
- remove_provisioning_net_mock,
- storage_detach_volumes_mock):
- obj_utils.create_test_volume_target(
- self.context, node_id=self.node.id)
- with task_manager.acquire(self.context,
- self.node.uuid, shared=False) as task:
- state = task.driver.deploy.tear_down(task)
- self.assertEqual(state, states.DELETED)
- node_power_action_mock.assert_called_once_with(task,
- states.POWER_OFF)
- unconfigure_tenant_nets_mock.assert_called_once_with(mock.ANY,
- task)
- remove_provisioning_net_mock.assert_called_once_with(mock.ANY,
- task)
- storage_detach_volumes_mock.assert_called_once_with(
- task.driver.storage, task)
- # Verify no volumes exist for new task instances.
- with task_manager.acquire(self.context,
- self.node.uuid, shared=False) as task:
- self.assertEqual(0, len(task.volume_targets))
-
- @mock.patch('ironic.common.dhcp_factory.DHCPFactory._set_dhcp_provider',
- autospec=True)
- @mock.patch('ironic.common.dhcp_factory.DHCPFactory.clean_dhcp',
- autospec=True)
- @mock.patch.object(pxe.PXEBoot, 'clean_up_instance', autospec=True)
- @mock.patch.object(pxe.PXEBoot, 'clean_up_ramdisk', autospec=True)
- @mock.patch.object(deploy_utils, 'destroy_images', autospec=True)
- def test_clean_up(self, destroy_images_mock, clean_up_ramdisk_mock,
- clean_up_instance_mock, clean_dhcp_mock,
- set_dhcp_provider_mock):
- with task_manager.acquire(self.context,
- self.node.uuid, shared=False) as task:
- task.driver.deploy.clean_up(task)
- destroy_images_mock.assert_called_once_with(task.node.uuid)
- clean_up_ramdisk_mock.assert_called_once_with(
- task.driver.boot, task)
- clean_up_instance_mock.assert_called_once_with(
- task.driver.boot, task)
- set_dhcp_provider_mock.assert_called_once_with()
- clean_dhcp_mock.assert_called_once_with(mock.ANY, task)
-
- @mock.patch.object(deploy_utils, 'prepare_inband_cleaning', autospec=True)
- def test_prepare_cleaning(self, prepare_inband_cleaning_mock):
- prepare_inband_cleaning_mock.return_value = states.CLEANWAIT
- with task_manager.acquire(self.context, self.node.uuid) as task:
- self.assertEqual(
- states.CLEANWAIT, task.driver.deploy.prepare_cleaning(task))
- prepare_inband_cleaning_mock.assert_called_once_with(
- task, manage_boot=True)
-
- @mock.patch.object(deploy_utils, 'tear_down_inband_cleaning',
- autospec=True)
- def test_tear_down_cleaning(self, tear_down_cleaning_mock):
- with task_manager.acquire(self.context, self.node.uuid) as task:
- task.driver.deploy.tear_down_cleaning(task)
- tear_down_cleaning_mock.assert_called_once_with(
- task, manage_boot=True)
-
- @mock.patch.object(agent_base, 'get_steps', autospec=True)
- def test_get_clean_steps(self, mock_get_clean_steps):
- # Test getting clean steps
- self.config(group='deploy', erase_devices_priority=10)
- self.config(group='deploy', erase_devices_metadata_priority=5)
- mock_steps = [{'priority': 10, 'interface': 'deploy',
- 'step': 'erase_devices'}]
- self.node.driver_internal_info = {'agent_url': 'foo'}
- self.node.save()
- mock_get_clean_steps.return_value = mock_steps
- with task_manager.acquire(self.context, self.node.uuid) as task:
- steps = task.driver.deploy.get_clean_steps(task)
- mock_get_clean_steps.assert_called_once_with(
- task, 'clean', interface='deploy',
- override_priorities={
- 'erase_devices': 10,
- 'erase_devices_metadata': 5})
- self.assertEqual(mock_steps, steps)
-
- @mock.patch.object(agent_base, 'execute_step', autospec=True)
- def test_execute_clean_step(self, agent_execute_clean_step_mock):
- with task_manager.acquire(self.context, self.node.uuid) as task:
- task.driver.deploy.execute_clean_step(
- task, {'some-step': 'step-info'})
- agent_execute_clean_step_mock.assert_called_once_with(
- task, {'some-step': 'step-info'}, 'clean')
-
- @mock.patch.object(iscsi_deploy, 'do_agent_iscsi_deploy', autospec=True)
- def test_write_image(self, do_agent_iscsi_deploy_mock):
-
- self.node.instance_info = {
- 'capabilities': {'boot_option': 'netboot'}}
- self.node.provision_state = states.DEPLOYWAIT
- self.node.target_provision_state = states.ACTIVE
- self.node.save()
- deployment_uuids = {'root uuid': 'some-root-uuid'}
- do_agent_iscsi_deploy_mock.return_value = deployment_uuids
- self.node.save()
- with task_manager.acquire(self.context, self.node.uuid) as task:
- task.driver.deploy.write_image(task)
- do_agent_iscsi_deploy_mock.assert_called_once_with(
- task, task.driver.deploy._client)
- self.assertEqual(
- task.node.driver_internal_info['deployment_uuids'],
- deployment_uuids)
-
- @mock.patch.object(noop_storage.NoopStorage, 'should_write_image',
- autospec=True)
- @mock.patch.object(iscsi_deploy, 'do_agent_iscsi_deploy', autospec=True)
- def test_write_image_bfv(self, do_agent_iscsi_deploy_mock,
- should_write_image_mock):
- should_write_image_mock.return_value = False
- with task_manager.acquire(self.context, self.node.uuid) as task:
- task.driver.deploy.write_image(task)
- self.assertFalse(do_agent_iscsi_deploy_mock.called)
-
- def test_prepare_instance_boot_netboot(self):
- deployment_uuids = {'root uuid': 'some-root-uuid'}
- self.node.instance_info = {
- 'capabilities': {'boot_option': 'netboot'}}
- self.node.provision_state = states.DEPLOYWAIT
- self.node.target_provision_state = states.ACTIVE
- info = self.node.driver_internal_info
- info['deployment_uuids'] = deployment_uuids
- self.node.driver_internal_info = info
- self.node.save()
-
- with task_manager.acquire(self.context, self.node.uuid) as task:
- with mock.patch.object(task.driver.boot,
- 'prepare_instance',
- autospec=True) as m_prep_instance:
- task.driver.deploy.prepare_instance_boot(task)
- m_prep_instance.assert_called_once_with(task)
-
- @mock.patch.object(fake.FakeManagement, 'set_boot_device', autospec=True)
- @mock.patch.object(agent_base.AgentDeployMixin,
- 'configure_local_boot', autospec=True)
- def test_prepare_instance_boot_localboot(self, configure_local_boot_mock,
- set_boot_device_mock):
-
- deployment_uuids = {'root uuid': 'some-root-uuid'}
- self.node.provision_state = states.DEPLOYWAIT
- self.node.target_provision_state = states.ACTIVE
- info = self.node.driver_internal_info
- info['deployment_uuids'] = deployment_uuids
- self.node.driver_internal_info = info
- self.node.save()
-
- with task_manager.acquire(self.context, self.node.uuid) as task:
- task.driver.deploy.prepare_instance_boot(task)
- configure_local_boot_mock.assert_called_once_with(
- task.driver.deploy, task, root_uuid='some-root-uuid',
- efi_system_part_uuid=None, prep_boot_part_uuid=None)
- set_boot_device_mock.assert_called_once_with(
- mock.ANY, task, device=boot_devices.DISK, persistent=True)
-
- @mock.patch.object(fake.FakeManagement, 'set_boot_device', autospec=True)
- @mock.patch.object(agent_base.AgentDeployMixin,
- 'configure_local_boot', autospec=True)
- def test_prepare_instance_boot_localboot_uefi(
- self, configure_local_boot_mock, set_boot_device_mock):
- deployment_uuids = {'root uuid': 'some-root-uuid',
- 'efi system partition uuid': 'efi-part-uuid'}
- self.node.instance_info = {
- 'capabilities': {'boot_option': 'local'}}
- self.node.provision_state = states.DEPLOYWAIT
- self.node.target_provision_state = states.ACTIVE
- info = self.node.driver_internal_info
- info['deployment_uuids'] = deployment_uuids
- self.node.driver_internal_info = info
- self.node.save()
-
- with task_manager.acquire(self.context, self.node.uuid) as task:
- task.driver.deploy.prepare_instance_boot(task)
- configure_local_boot_mock.assert_called_once_with(
- task.driver.deploy, task, root_uuid='some-root-uuid',
- efi_system_part_uuid='efi-part-uuid', prep_boot_part_uuid=None)
- set_boot_device_mock.assert_called_once_with(
- mock.ANY, task, device=boot_devices.DISK, persistent=True)
-
- @mock.patch.object(iscsi_deploy, 'do_agent_iscsi_deploy', autospec=True)
- @mock.patch.object(utils, 'is_memory_insufficent', autospec=True)
- def test_write_image_out_of_memory(self, mock_memory_check,
- mock_do_iscsi_deploy):
- mock_memory_check.return_value = True
- self.node.provision_state = states.DEPLOYWAIT
- self.node.target_provision_state = states.ACTIVE
- self.node.save()
- with task_manager.acquire(self.context, self.node.uuid) as task:
- value = task.driver.deploy.write_image(task)
- self.assertEqual(states.DEPLOYWAIT, value)
- self.assertEqual(states.DEPLOYWAIT, task.node.provision_state)
- self.assertIn('skip_current_deploy_step',
- task.node.driver_internal_info)
- self.assertTrue(mock_memory_check.called)
- self.assertFalse(mock_do_iscsi_deploy.called)
-
- @mock.patch.object(manager_utils, 'restore_power_state_if_needed',
- autospec=True)
- @mock.patch.object(manager_utils, 'power_on_node_if_needed', autospec=True)
- @mock.patch.object(noop_storage.NoopStorage, 'attach_volumes',
- autospec=True)
- @mock.patch.object(deploy_utils, 'populate_storage_driver_internal_info',
- autospec=True)
- @mock.patch.object(deploy_utils, 'build_agent_options', autospec=True)
- @mock.patch.object(pxe.PXEBoot, 'prepare_ramdisk', autospec=True)
- @mock.patch.object(flat_network.FlatNetwork, 'add_provisioning_network',
- spec_set=True, autospec=True)
- @mock.patch.object(flat_network.FlatNetwork,
- 'unconfigure_tenant_networks',
- spec_set=True, autospec=True)
- def test_prepare_node_deploying_with_smartnic_port(
- self, unconfigure_tenant_net_mock, add_provisioning_net_mock,
- mock_prepare_ramdisk, mock_agent_options,
- storage_driver_info_mock, storage_attach_volumes_mock,
- power_on_node_if_needed_mock, restore_power_state_mock):
- mock_agent_options.return_value = {'c': 'd'}
- with task_manager.acquire(self.context, self.node.uuid) as task:
- task.node.provision_state = states.DEPLOYING
- power_on_node_if_needed_mock.return_value = states.POWER_OFF
- task.driver.deploy.prepare(task)
- mock_agent_options.assert_called_once_with(task.node)
- mock_prepare_ramdisk.assert_called_once_with(
- task.driver.boot, task, {'c': 'd'})
- add_provisioning_net_mock.assert_called_once_with(mock.ANY, task)
- unconfigure_tenant_net_mock.assert_called_once_with(mock.ANY, task)
- storage_driver_info_mock.assert_called_once_with(task)
- storage_attach_volumes_mock.assert_called_once_with(
- task.driver.storage, task)
- power_on_node_if_needed_mock.assert_called_once_with(task)
- restore_power_state_mock.assert_called_once_with(
- task, states.POWER_OFF)
-
- @mock.patch.object(manager_utils, 'restore_power_state_if_needed',
- autospec=True)
- @mock.patch.object(manager_utils, 'power_on_node_if_needed', autospec=True)
- @mock.patch.object(noop_storage.NoopStorage, 'detach_volumes',
- autospec=True)
- @mock.patch.object(flat_network.FlatNetwork,
- 'remove_provisioning_network',
- spec_set=True, autospec=True)
- @mock.patch.object(flat_network.FlatNetwork,
- 'unconfigure_tenant_networks',
- spec_set=True, autospec=True)
- @mock.patch.object(manager_utils, 'node_power_action', autospec=True)
- def test_tear_down_with_smartnic_port(
- self, node_power_action_mock, unconfigure_tenant_nets_mock,
- remove_provisioning_net_mock, storage_detach_volumes_mock,
- power_on_node_if_needed_mock, restore_power_state_mock):
- obj_utils.create_test_volume_target(
- self.context, node_id=self.node.id)
- with task_manager.acquire(
- self.context, self.node.uuid, shared=False) as task:
- power_on_node_if_needed_mock.return_value = states.POWER_OFF
- state = task.driver.deploy.tear_down(task)
- self.assertEqual(state, states.DELETED)
- node_power_action_mock.assert_called_once_with(
- task, states.POWER_OFF)
- unconfigure_tenant_nets_mock.assert_called_once_with(
- mock.ANY, task)
- remove_provisioning_net_mock.assert_called_once_with(
- mock.ANY, task)
- storage_detach_volumes_mock.assert_called_once_with(
- task.driver.storage, task)
- power_on_node_if_needed_mock.assert_called_once_with(task)
- restore_power_state_mock.assert_called_once_with(
- task, states.POWER_OFF)
- # Verify no volumes exist for new task instances.
- with task_manager.acquire(self.context,
- self.node.uuid, shared=False) as task:
- self.assertEqual(0, len(task.volume_targets))
-
-
-# Cleanup of iscsi_deploy with pxe boot interface
-class CleanUpFullFlowTestCase(db_base.DbTestCase):
- def setUp(self):
- super(CleanUpFullFlowTestCase, self).setUp()
- self.config(image_cache_size=0, group='pxe')
-
- # Configure node
- instance_info = INST_INFO_DICT
- instance_info['deploy_key'] = 'fake-56789'
- self.node = obj_utils.create_test_node(
- self.context, boot_interface='pxe', deploy_interface='iscsi',
- instance_info=instance_info,
- driver_info=DRV_INFO_DICT,
- driver_internal_info=DRV_INTERNAL_INFO_DICT,
- )
- self.port = obj_utils.create_test_port(self.context,
- node_id=self.node.id)
-
- # Configure temporary directories
- pxe_temp_dir = tempfile.mkdtemp()
- self.config(tftp_root=pxe_temp_dir, group='pxe')
- tftp_master_dir = os.path.join(CONF.pxe.tftp_root,
- 'tftp_master')
- self.config(tftp_master_path=tftp_master_dir, group='pxe')
- os.makedirs(tftp_master_dir)
-
- instance_temp_dir = tempfile.mkdtemp()
- self.config(images_path=instance_temp_dir,
- group='pxe')
- instance_master_dir = os.path.join(CONF.pxe.images_path,
- 'instance_master')
- self.config(instance_master_path=instance_master_dir,
- group='pxe')
- os.makedirs(instance_master_dir)
- self.pxe_config_dir = os.path.join(CONF.pxe.tftp_root, 'pxelinux.cfg')
- os.makedirs(self.pxe_config_dir)
-
- # Populate some file names
- self.master_kernel_path = os.path.join(CONF.pxe.tftp_master_path,
- 'kernel')
- self.master_instance_path = os.path.join(CONF.pxe.instance_master_path,
- 'image_uuid')
- self.node_tftp_dir = os.path.join(CONF.pxe.tftp_root,
- self.node.uuid)
- os.makedirs(self.node_tftp_dir)
- self.kernel_path = os.path.join(self.node_tftp_dir,
- 'kernel')
- self.node_image_dir = deploy_utils._get_image_dir_path(self.node.uuid)
- os.makedirs(self.node_image_dir)
- self.image_path = deploy_utils._get_image_file_path(self.node.uuid)
- self.config_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
- self.mac_path = pxe_utils._get_pxe_mac_path(self.port.address)
-
- # Create files
- self.files = [self.config_path, self.master_kernel_path,
- self.master_instance_path]
- for fname in self.files:
- # NOTE(dtantsur): files with 0 size won't be cleaned up
- with open(fname, 'w') as fp:
- fp.write('test')
-
- os.link(self.config_path, self.mac_path)
- os.link(self.master_kernel_path, self.kernel_path)
- os.link(self.master_instance_path, self.image_path)
- dhcp_factory.DHCPFactory._dhcp_provider = None
-
- @mock.patch('ironic.common.dhcp_factory.DHCPFactory._set_dhcp_provider',
- autospec=True)
- @mock.patch('ironic.common.dhcp_factory.DHCPFactory.clean_dhcp',
- autospec=True)
- @mock.patch.object(pxe_utils, 'get_instance_image_info', autospec=True)
- @mock.patch.object(pxe_utils, 'get_image_info', autospec=True)
- def test_clean_up_with_master(self, mock_get_deploy_image_info,
- mock_get_instance_image_info,
- clean_dhcp_mock, set_dhcp_provider_mock):
- image_info = {'kernel': ('kernel_uuid',
- self.kernel_path)}
- mock_get_instance_image_info.return_value = image_info
- mock_get_deploy_image_info.return_value = {}
-
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- task.driver.deploy.clean_up(task)
- mock_get_instance_image_info.assert_called_with(task,
- ipxe_enabled=False)
- mock_get_deploy_image_info.assert_called_with(
- task.node, mode='deploy', ipxe_enabled=False)
- set_dhcp_provider_mock.assert_called_once_with()
- clean_dhcp_mock.assert_called_once_with(mock.ANY, task)
- for path in ([self.kernel_path, self.image_path, self.config_path]
- + self.files):
- self.assertFalse(os.path.exists(path),
- '%s is not expected to exist' % path)
-
-
-@mock.patch.object(time, 'sleep', lambda seconds: None)
-class PhysicalWorkTestCase(tests_base.TestCase):
-
- def setUp(self):
- super(PhysicalWorkTestCase, self).setUp()
- self.address = '127.0.0.1'
- self.port = 3306
- self.iqn = 'iqn.xyz'
- self.lun = 1
- self.image_path = '/tmp/xyz/image'
- self.node_uuid = "12345678-1234-1234-1234-1234567890abcxyz"
- self.dev = ("/dev/disk/by-path/ip-%s:%s-iscsi-%s-lun-%s"
- % (self.address, self.port, self.iqn, self.lun))
-
- def _mock_calls(self, name_list, module):
- patch_list = [mock.patch.object(module, name,
- spec_set=types.FunctionType)
- for name in name_list]
- mock_list = [patcher.start() for patcher in patch_list]
- for patcher in patch_list:
- self.addCleanup(patcher.stop)
-
- parent_mock = mock.MagicMock(spec=[])
- for mocker, name in zip(mock_list, name_list):
- parent_mock.attach_mock(mocker, name)
- return parent_mock
-
- @mock.patch.object(disk_utils, 'work_on_disk', autospec=True)
- @mock.patch.object(disk_utils, 'is_block_device', autospec=True)
- @mock.patch.object(disk_utils, 'get_image_mb', autospec=True)
- @mock.patch.object(iscsi_deploy, 'logout_iscsi', autospec=True)
- @mock.patch.object(iscsi_deploy, 'login_iscsi', autospec=True)
- @mock.patch.object(iscsi_deploy, 'discovery', autospec=True)
- @mock.patch.object(iscsi_deploy, 'delete_iscsi', autospec=True)
- def _test_deploy_partition_image(self,
- mock_delete_iscsi,
- mock_discovery,
- mock_login_iscsi,
- mock_logout_iscsi,
- mock_get_image_mb,
- mock_is_block_device,
- mock_work_on_disk, **kwargs):
- # Below are the only values we allow callers to modify for testing.
- # Check that values other than this aren't passed in.
- deploy_args = {
- 'boot_mode': None,
- 'boot_option': None,
- 'configdrive': None,
- 'cpu_arch': None,
- 'disk_label': None,
- 'ephemeral_format': None,
- 'ephemeral_mb': None,
- 'image_mb': 1,
- 'preserve_ephemeral': False,
- 'root_mb': 128,
- 'swap_mb': 64
- }
- disallowed_values = set(kwargs) - set(deploy_args)
- if disallowed_values:
- raise ValueError("Only the following kwargs are allowed in "
- "_test_deploy_partition_image: %(allowed)s. "
- "Disallowed values: %(disallowed)s."
- % {"allowed": ", ".join(deploy_args),
- "disallowed": ", ".join(disallowed_values)})
- deploy_args.update(kwargs)
-
- root_uuid = '12345678-1234-1234-12345678-12345678abcdef'
-
- mock_is_block_device.return_value = True
- mock_get_image_mb.return_value = deploy_args['image_mb']
- mock_work_on_disk.return_value = {
- 'root uuid': root_uuid,
- 'efi system partition uuid': None
- }
-
- deploy_kwargs = {
- 'boot_mode': deploy_args['boot_mode'],
- 'boot_option': deploy_args['boot_option'],
- 'configdrive': deploy_args['configdrive'],
- 'disk_label': deploy_args['disk_label'],
- 'cpu_arch': deploy_args['cpu_arch'] or '',
- 'preserve_ephemeral': deploy_args['preserve_ephemeral']
- }
- iscsi_deploy.deploy_partition_image(
- self.address, self.port, self.iqn, self.lun, self.image_path,
- deploy_args['root_mb'],
- deploy_args['swap_mb'], deploy_args['ephemeral_mb'],
- deploy_args['ephemeral_format'], self.node_uuid, **deploy_kwargs)
-
- mock_discovery.assert_called_once_with(self.address, self.port)
- mock_login_iscsi.assert_called_once_with(self.address, self.port,
- self.iqn)
- mock_logout_iscsi.assert_called_once_with(self.address, self.port,
- self.iqn)
- mock_delete_iscsi.assert_called_once_with(self.address, self.port,
- self.iqn)
- mock_get_image_mb.assert_called_once_with(self.image_path)
- mock_is_block_device.assert_called_once_with(self.dev)
-
- work_on_disk_kwargs = {
- 'preserve_ephemeral': deploy_args['preserve_ephemeral'],
- 'configdrive': deploy_args['configdrive'],
- # boot_option defaults to 'netboot' if
- # not set
- 'boot_option': deploy_args['boot_option'] or 'local',
- 'boot_mode': deploy_args['boot_mode'],
- 'disk_label': deploy_args['disk_label'],
- 'cpu_arch': deploy_args['cpu_arch'] or ''
- }
- mock_work_on_disk.assert_called_once_with(
- self.dev, deploy_args['root_mb'], deploy_args['swap_mb'],
- deploy_args['ephemeral_mb'], deploy_args['ephemeral_format'],
- self.image_path, self.node_uuid, **work_on_disk_kwargs)
-
- def test_deploy_partition_image_without_boot_option(self):
- self._test_deploy_partition_image()
-
- def test_deploy_partition_image_netboot(self):
- self._test_deploy_partition_image(boot_option="netboot")
-
- def test_deploy_partition_image_localboot(self):
- self._test_deploy_partition_image(boot_option="local")
-
- def test_deploy_partition_image_wo_boot_option_and_wo_boot_mode(self):
- self._test_deploy_partition_image()
-
- def test_deploy_partition_image_netboot_bios(self):
- self._test_deploy_partition_image(boot_option="netboot",
- boot_mode="bios")
-
- def test_deploy_partition_image_localboot_bios(self):
- self._test_deploy_partition_image(boot_option="local",
- boot_mode="bios")
-
- def test_deploy_partition_image_netboot_uefi(self):
- self._test_deploy_partition_image(boot_option="netboot",
- boot_mode="uefi")
-
- def test_deploy_partition_image_disk_label(self):
- self._test_deploy_partition_image(disk_label='gpt')
-
- def test_deploy_partition_image_image_exceeds_root_partition(self):
- self.assertRaises(exception.InstanceDeployFailure,
- self._test_deploy_partition_image, image_mb=129,
- root_mb=128)
-
- def test_deploy_partition_image_localboot_uefi(self):
- self._test_deploy_partition_image(boot_option="local",
- boot_mode="uefi")
-
- def test_deploy_partition_image_without_swap(self):
- self._test_deploy_partition_image(swap_mb=0)
-
- def test_deploy_partition_image_with_ephemeral(self):
- self._test_deploy_partition_image(ephemeral_format='exttest',
- ephemeral_mb=256)
-
- def test_deploy_partition_image_preserve_ephemeral(self):
- self._test_deploy_partition_image(ephemeral_format='exttest',
- ephemeral_mb=256,
- preserve_ephemeral=True)
-
- def test_deploy_partition_image_with_configdrive(self):
- self._test_deploy_partition_image(configdrive='http://1.2.3.4/cd')
-
- def test_deploy_partition_image_with_cpu_arch(self):
- self._test_deploy_partition_image(cpu_arch='generic')
-
- @mock.patch.object(disk_utils, 'create_config_drive_partition',
- autospec=True)
- @mock.patch.object(disk_utils, 'get_disk_identifier', autospec=True)
- def test_deploy_whole_disk_image(self, mock_gdi, create_config_drive_mock):
- """Check loosely all functions are called with right args."""
-
- name_list = ['discovery', 'login_iscsi',
- 'logout_iscsi', 'delete_iscsi']
- disk_utils_name_list = ['is_block_device', 'populate_image']
-
- iscsi_mock = self._mock_calls(name_list, iscsi_deploy)
-
- disk_utils_mock = self._mock_calls(disk_utils_name_list, disk_utils)
- disk_utils_mock.is_block_device.return_value = True
- mock_gdi.return_value = '0x12345678'
- utils_calls_expected = [mock.call.discovery(self.address, self.port),
- mock.call.login_iscsi(self.address, self.port,
- self.iqn),
- mock.call.logout_iscsi(self.address, self.port,
- self.iqn),
- mock.call.delete_iscsi(self.address, self.port,
- self.iqn)]
- disk_utils_calls_expected = [mock.call.is_block_device(self.dev),
- mock.call.populate_image(self.image_path,
- self.dev,
- conv_flags=None)]
- uuid_dict_returned = iscsi_deploy.deploy_disk_image(
- self.address, self.port, self.iqn, self.lun, self.image_path,
- self.node_uuid)
-
- self.assertEqual(utils_calls_expected, iscsi_mock.mock_calls)
- self.assertEqual(disk_utils_calls_expected, disk_utils_mock.mock_calls)
- self.assertFalse(create_config_drive_mock.called)
- self.assertEqual('0x12345678', uuid_dict_returned['disk identifier'])
-
- @mock.patch.object(disk_utils, 'create_config_drive_partition',
- autospec=True)
- @mock.patch.object(disk_utils, 'get_disk_identifier', autospec=True)
- def test_deploy_whole_disk_image_with_config_drive(self, mock_gdi,
- create_partition_mock):
- """Check loosely all functions are called with right args."""
- config_url = 'http://1.2.3.4/cd'
-
- iscsi_list = ['discovery', 'login_iscsi', 'logout_iscsi',
- 'delete_iscsi']
-
- disk_utils_list = ['is_block_device', 'populate_image']
- iscsi_mock = self._mock_calls(iscsi_list, iscsi_deploy)
- disk_utils_mock = self._mock_calls(disk_utils_list, disk_utils)
- disk_utils_mock.is_block_device.return_value = True
- mock_gdi.return_value = '0x12345678'
- utils_calls_expected = [mock.call.discovery(self.address, self.port),
- mock.call.login_iscsi(self.address, self.port,
- self.iqn),
- mock.call.logout_iscsi(self.address, self.port,
- self.iqn),
- mock.call.delete_iscsi(self.address, self.port,
- self.iqn)]
-
- disk_utils_calls_expected = [mock.call.is_block_device(self.dev),
- mock.call.populate_image(self.image_path,
- self.dev,
- conv_flags=None)]
-
- uuid_dict_returned = iscsi_deploy.deploy_disk_image(
- self.address, self.port, self.iqn, self.lun, self.image_path,
- self.node_uuid, configdrive=config_url)
-
- iscsi_mock.assert_has_calls(utils_calls_expected)
- disk_utils_mock.assert_has_calls(disk_utils_calls_expected)
- create_partition_mock.assert_called_once_with(self.node_uuid, self.dev,
- config_url)
- self.assertEqual('0x12345678', uuid_dict_returned['disk identifier'])
-
- @mock.patch.object(disk_utils, 'create_config_drive_partition',
- autospec=True)
- @mock.patch.object(disk_utils, 'get_disk_identifier', autospec=True)
- def test_deploy_whole_disk_image_sparse(self, mock_gdi,
- create_config_drive_mock):
- """Check loosely all functions are called with right args."""
- iscsi_name_list = ['discovery', 'login_iscsi',
- 'logout_iscsi', 'delete_iscsi']
- disk_utils_name_list = ['is_block_device', 'populate_image']
-
- iscsi_mock = self._mock_calls(iscsi_name_list, iscsi_deploy)
-
- disk_utils_mock = self._mock_calls(disk_utils_name_list, disk_utils)
- disk_utils_mock.is_block_device.return_value = True
- mock_gdi.return_value = '0x12345678'
- utils_calls_expected = [mock.call.discovery(self.address, self.port),
- mock.call.login_iscsi(self.address, self.port,
- self.iqn),
- mock.call.logout_iscsi(self.address, self.port,
- self.iqn),
- mock.call.delete_iscsi(self.address, self.port,
- self.iqn)]
- disk_utils_calls_expected = [mock.call.is_block_device(self.dev),
- mock.call.populate_image(
- self.image_path, self.dev,
- conv_flags='sparse')]
-
- uuid_dict_returned = iscsi_deploy.deploy_disk_image(
- self.address, self.port, self.iqn, self.lun, self.image_path,
- self.node_uuid, configdrive=None, conv_flags='sparse')
-
- self.assertEqual(utils_calls_expected, iscsi_mock.mock_calls)
- self.assertEqual(disk_utils_calls_expected, disk_utils_mock.mock_calls)
- self.assertFalse(create_config_drive_mock.called)
- self.assertEqual('0x12345678', uuid_dict_returned['disk identifier'])
-
- @mock.patch.object(utils, 'execute', autospec=True)
- def test_verify_iscsi_connection_raises(self, mock_exec):
- iqn = 'iqn.xyz'
- mock_exec.return_value = ['iqn.abc', '']
- self.assertRaises(exception.InstanceDeployFailure,
- iscsi_deploy.verify_iscsi_connection, iqn)
- self.assertEqual(3, mock_exec.call_count)
-
- @mock.patch.object(utils, 'execute', autospec=True)
- def test_verify_iscsi_connection_override_attempts(self, mock_exec):
- utils.CONF.set_override('verify_attempts', 2, group='iscsi')
- iqn = 'iqn.xyz'
- mock_exec.return_value = ['iqn.abc', '']
- self.assertRaises(exception.InstanceDeployFailure,
- iscsi_deploy.verify_iscsi_connection, iqn)
- self.assertEqual(2, mock_exec.call_count)
-
- @mock.patch.object(os.path, 'exists', autospec=True)
- def test_check_file_system_for_iscsi_device_raises(self, mock_os):
- iqn = 'iqn.xyz'
- ip = "127.0.0.1"
- port = "22"
- mock_os.return_value = False
- self.assertRaises(exception.InstanceDeployFailure,
- iscsi_deploy.check_file_system_for_iscsi_device,
- ip, port, iqn)
- self.assertEqual(3, mock_os.call_count)
-
- @mock.patch.object(os.path, 'exists', autospec=True)
- def test_check_file_system_for_iscsi_device(self, mock_os):
- iqn = 'iqn.xyz'
- ip = "127.0.0.1"
- port = "22"
- check_dir = "/dev/disk/by-path/ip-%s:%s-iscsi-%s-lun-1" % (ip,
- port,
- iqn)
-
- mock_os.return_value = True
- iscsi_deploy.check_file_system_for_iscsi_device(ip, port, iqn)
- mock_os.assert_called_once_with(check_dir)
-
- @mock.patch.object(utils, 'execute', autospec=True)
- def test_verify_iscsi_connection(self, mock_exec):
- iqn = 'iqn.xyz'
- mock_exec.return_value = ['iqn.xyz', '']
- iscsi_deploy.verify_iscsi_connection(iqn)
- mock_exec.assert_called_once_with(
- 'iscsiadm',
- '-m', 'node',
- '-S',
- run_as_root=True)
-
- @mock.patch.object(utils, 'execute', autospec=True)
- def test_force_iscsi_lun_update(self, mock_exec):
- iqn = 'iqn.xyz'
- iscsi_deploy.force_iscsi_lun_update(iqn)
- mock_exec.assert_called_once_with(
- 'iscsiadm',
- '-m', 'node',
- '-T', iqn,
- '-R',
- run_as_root=True)
-
- @mock.patch.object(utils, 'execute', autospec=True)
- @mock.patch.object(iscsi_deploy, 'verify_iscsi_connection', autospec=True)
- @mock.patch.object(iscsi_deploy, 'force_iscsi_lun_update', autospec=True)
- @mock.patch.object(iscsi_deploy, 'check_file_system_for_iscsi_device',
- autospec=True)
- def test_login_iscsi_calls_verify_and_update(self,
- mock_check_dev,
- mock_update,
- mock_verify,
- mock_exec):
- address = '127.0.0.1'
- port = 3306
- iqn = 'iqn.xyz'
- mock_exec.return_value = ['iqn.xyz', '']
- iscsi_deploy.login_iscsi(address, port, iqn)
- mock_exec.assert_called_once_with(
- 'iscsiadm',
- '-m', 'node',
- '-p', '%s:%s' % (address, port),
- '-T', iqn,
- '--login',
- run_as_root=True,
- attempts=5,
- delay_on_retry=True)
-
- mock_verify.assert_called_once_with(iqn)
- mock_update.assert_called_once_with(iqn)
- mock_check_dev.assert_called_once_with(address, port, iqn)
-
- @mock.patch.object(iscsi_deploy, 'LOG', autospec=True)
- @mock.patch.object(utils, 'execute', autospec=True)
- @mock.patch.object(iscsi_deploy, 'verify_iscsi_connection', autospec=True)
- @mock.patch.object(iscsi_deploy, 'force_iscsi_lun_update', autospec=True)
- @mock.patch.object(iscsi_deploy, 'check_file_system_for_iscsi_device',
- autospec=True)
- @mock.patch.object(iscsi_deploy, 'delete_iscsi', autospec=True)
- @mock.patch.object(iscsi_deploy, 'logout_iscsi', autospec=True)
- def test_login_iscsi_calls_raises(
- self, mock_loiscsi, mock_discsi, mock_check_dev, mock_update,
- mock_verify, mock_exec, mock_log):
- address = '127.0.0.1'
- port = 3306
- iqn = 'iqn.xyz'
- mock_exec.return_value = ['iqn.xyz', '']
- mock_check_dev.side_effect = exception.InstanceDeployFailure('boom')
- self.assertRaises(exception.InstanceDeployFailure,
- iscsi_deploy.login_iscsi,
- address, port, iqn)
- mock_verify.assert_called_once_with(iqn)
- mock_update.assert_called_once_with(iqn)
- mock_loiscsi.assert_called_once_with(address, port, iqn)
- mock_discsi.assert_called_once_with(address, port, iqn)
- self.assertIsInstance(mock_log.error.call_args[0][1],
- exception.InstanceDeployFailure)
-
- @mock.patch.object(iscsi_deploy, 'LOG', autospec=True)
- @mock.patch.object(utils, 'execute', autospec=True)
- @mock.patch.object(iscsi_deploy, 'verify_iscsi_connection', autospec=True)
- @mock.patch.object(iscsi_deploy, 'force_iscsi_lun_update', autospec=True)
- @mock.patch.object(iscsi_deploy, 'check_file_system_for_iscsi_device',
- autospec=True)
- @mock.patch.object(iscsi_deploy, 'delete_iscsi', autospec=True)
- @mock.patch.object(iscsi_deploy, 'logout_iscsi', autospec=True)
- def test_login_iscsi_calls_raises_during_cleanup(
- self, mock_loiscsi, mock_discsi, mock_check_dev, mock_update,
- mock_verify, mock_exec, mock_log):
- address = '127.0.0.1'
- port = 3306
- iqn = 'iqn.xyz'
- mock_exec.return_value = ['iqn.xyz', '']
- mock_check_dev.side_effect = exception.InstanceDeployFailure('boom')
- mock_discsi.side_effect = processutils.ProcessExecutionError('boom')
- self.assertRaises(exception.InstanceDeployFailure,
- iscsi_deploy.login_iscsi,
- address, port, iqn)
- mock_verify.assert_called_once_with(iqn)
- mock_update.assert_called_once_with(iqn)
- mock_loiscsi.assert_called_once_with(address, port, iqn)
- mock_discsi.assert_called_once_with(address, port, iqn)
- self.assertIsInstance(mock_log.error.call_args[0][1],
- exception.InstanceDeployFailure)
- self.assertIsInstance(mock_log.warning.call_args[0][1],
- processutils.ProcessExecutionError)
-
- @mock.patch.object(disk_utils, 'is_block_device', lambda d: True)
- def test_always_logout_and_delete_iscsi(self):
- """Check if logout_iscsi() and delete_iscsi() are called.
-
- Make sure that logout_iscsi() and delete_iscsi() are called once
- login_iscsi() is invoked.
-
- """
- address = '127.0.0.1'
- port = 3306
- iqn = 'iqn.xyz'
- lun = 1
- image_path = '/tmp/xyz/image'
- root_mb = 128
- swap_mb = 64
- ephemeral_mb = 256
- ephemeral_format = 'exttest'
- node_uuid = "12345678-1234-1234-1234-1234567890abcxyz"
-
- class TestException(Exception):
- pass
-
- iscsi_name_list = ['discovery', 'login_iscsi',
- 'logout_iscsi', 'delete_iscsi']
-
- disk_utils_name_list = ['get_image_mb', 'work_on_disk']
-
- iscsi_mock = self._mock_calls(iscsi_name_list, iscsi_deploy)
-
- disk_utils_mock = self._mock_calls(disk_utils_name_list, disk_utils)
- disk_utils_mock.get_image_mb.return_value = 1
- disk_utils_mock.work_on_disk.side_effect = TestException
- utils_calls_expected = [mock.call.discovery(address, port),
- mock.call.login_iscsi(address, port, iqn),
- mock.call.logout_iscsi(address, port, iqn),
- mock.call.delete_iscsi(address, port, iqn)]
- disk_utils_calls_expected = [mock.call.get_image_mb(image_path),
- mock.call.work_on_disk(
- self.dev, root_mb, swap_mb,
- ephemeral_mb,
- ephemeral_format, image_path,
- node_uuid, configdrive=None,
- preserve_ephemeral=False,
- boot_option="local",
- boot_mode="bios",
- disk_label=None,
- cpu_arch="")]
-
- self.assertRaises(TestException, iscsi_deploy.deploy_partition_image,
- address, port, iqn, lun, image_path,
- root_mb, swap_mb, ephemeral_mb, ephemeral_format,
- node_uuid)
-
- self.assertEqual(utils_calls_expected, iscsi_mock.mock_calls)
- self.assertEqual(disk_utils_calls_expected, disk_utils_mock.mock_calls)
-
- @mock.patch.object(utils, 'execute', autospec=True)
- @mock.patch.object(iscsi_deploy, 'verify_iscsi_connection', autospec=True)
- @mock.patch.object(iscsi_deploy, 'force_iscsi_lun_update', autospec=True)
- @mock.patch.object(iscsi_deploy, 'check_file_system_for_iscsi_device',
- autospec=True)
- def test_ipv6_address_wrapped(self,
- mock_check_dev,
- mock_update,
- mock_verify,
- mock_exec):
- address = '2001:DB8::1111'
- port = 3306
- iqn = 'iqn.xyz'
- mock_exec.return_value = ['iqn.xyz', '']
- iscsi_deploy.login_iscsi(address, port, iqn)
- mock_exec.assert_called_once_with(
- 'iscsiadm',
- '-m', 'node',
- '-p', '[%s]:%s' % (address, port),
- '-T', iqn,
- '--login',
- run_as_root=True,
- attempts=5,
- delay_on_retry=True)
-
-
-@mock.patch.object(disk_utils, 'is_block_device', autospec=True)
-@mock.patch.object(iscsi_deploy, 'login_iscsi', lambda *_: None)
-@mock.patch.object(iscsi_deploy, 'discovery', lambda *_: None)
-@mock.patch.object(iscsi_deploy, 'logout_iscsi', lambda *_: None)
-@mock.patch.object(iscsi_deploy, 'delete_iscsi', lambda *_: None)
-class ISCSISetupAndHandleErrorsTestCase(tests_base.TestCase):
-
- def test_no_parent_device(self, mock_ibd):
- address = '127.0.0.1'
- port = 3306
- iqn = 'iqn.xyz'
- lun = 1
- mock_ibd.return_value = False
- expected_dev = ("/dev/disk/by-path/ip-%s:%s-iscsi-%s-lun-%s"
- % (address, port, iqn, lun))
- with testtools.ExpectedException(exception.InstanceDeployFailure):
- with iscsi_deploy._iscsi_setup_and_handle_errors(
- address, port, iqn, lun) as dev:
- self.assertEqual(expected_dev, dev)
-
- mock_ibd.assert_called_once_with(expected_dev)
-
- def test_parent_device_yield(self, mock_ibd):
- address = '127.0.0.1'
- port = 3306
- iqn = 'iqn.xyz'
- lun = 1
- expected_dev = ("/dev/disk/by-path/ip-%s:%s-iscsi-%s-lun-%s"
- % (address, port, iqn, lun))
- mock_ibd.return_value = True
- with iscsi_deploy._iscsi_setup_and_handle_errors(
- address, port, iqn, lun) as dev:
- self.assertEqual(expected_dev, dev)
-
- mock_ibd.assert_called_once_with(expected_dev)
diff --git a/ironic/tests/unit/drivers/modules/test_pxe.py b/ironic/tests/unit/drivers/modules/test_pxe.py
index 4b06a495a..af05fcd6d 100644
--- a/ironic/tests/unit/drivers/modules/test_pxe.py
+++ b/ironic/tests/unit/drivers/modules/test_pxe.py
@@ -79,8 +79,7 @@ class PXEBootTestCase(db_base.DbTestCase):
self.config(enabled_boot_interfaces=[self.boot_interface,
'ipxe', 'fake'])
- self.config(enabled_deploy_interfaces=['fake', 'direct', 'iscsi',
- 'anaconda'])
+ self.config(enabled_deploy_interfaces=['fake', 'direct', 'anaconda'])
self.node = obj_utils.create_test_node(
self.context,
driver=self.driver,
diff --git a/ironic/tests/unit/objects/test_conductor.py b/ironic/tests/unit/objects/test_conductor.py
index 6df22c838..4b3c95490 100644
--- a/ironic/tests/unit/objects/test_conductor.py
+++ b/ironic/tests/unit/objects/test_conductor.py
@@ -166,9 +166,9 @@ class TestConductorObject(db_base.DbTestCase):
def test_register_hardware_interfaces(self):
host = self.fake_conductor['hostname']
- self.config(default_deploy_interface='iscsi')
+ self.config(default_deploy_interface='ansible')
arg = [{"hardware_type": "hardware-type", "interface_type": "deploy",
- "interface_name": "iscsi", "default": True},
+ "interface_name": "ansible", "default": True},
{"hardware_type": "hardware-type", "interface_type": "deploy",
"interface_name": "direct", "default": False}]
with mock.patch.object(self.dbapi, 'get_conductor',
diff --git a/releasenotes/notes/bye-bye-iscsi-658920cf126db0b8.yaml b/releasenotes/notes/bye-bye-iscsi-658920cf126db0b8.yaml
new file mode 100644
index 000000000..4965a63c0
--- /dev/null
+++ b/releasenotes/notes/bye-bye-iscsi-658920cf126db0b8.yaml
@@ -0,0 +1,5 @@
+---
+upgrade:
+ - |
+ The deprecated ``iscsi`` deploy interface has been removed. Please update
+ to a different deploy interface before upgrading.
diff --git a/setup.cfg b/setup.cfg
index a6719d46a..727b536ed 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -90,7 +90,6 @@ ironic.hardware.interfaces.deploy =
custom-agent = ironic.drivers.modules.agent:CustomAgentDeploy
direct = ironic.drivers.modules.agent:AgentDeploy
fake = ironic.drivers.modules.fake:FakeDeploy
- iscsi = ironic.drivers.modules.iscsi_deploy:ISCSIDeploy
ramdisk = ironic.drivers.modules.pxe:PXERamdiskDeploy
ironic.hardware.interfaces.inspect =