├── .gitignore ├── CHANGELOG ├── LICENSE ├── Makefile ├── README.md ├── README.migration ├── invalid ├── README ├── config1 ├── config2 ├── config3 ├── config4 ├── config5 ├── runtime1 └── runtime2 ├── lrbd ├── lrbd.spec ├── man ├── lrbd.8 └── lrbd.conf.5 ├── samples ├── 2gateways+2images+2targets+no_authentication.json ├── 2gateways+2images+assigned_lun+no_authentication.json ├── 2gateways+2images+no_authentication.json ├── 2gateways+2portals+2images+isolated+no_authentication.json ├── 2gateways+2portals+2images+no_authentication.json ├── 2gateways+2portals+no_authentication.json ├── 2gateways+no_authentication.json ├── 2gateways+tpg+identified+settings.json ├── 2gateways+tpg+identified.json ├── 2plain+3gateways+2portals+2images+isolated+no_authentication.json ├── 3gateways+2portals+2images+isolated+no_authentication.json ├── 3gateways+80targets+no_authentication.json ├── 3gateways+no_authentication.json ├── 3gateways+tpg+identified.json ├── README.NEW ├── acls+discovery+mutual.json ├── acls+discovery.json ├── acls+mutual+discovery+mutual.json ├── acls+mutual+discovery.json ├── acls+mutual.json ├── acls+settings.json ├── acls.json ├── complete.json ├── identified+settings.json ├── identified.json ├── no_authentication+explicit.json ├── no_authentication.json ├── nonstandard_port+no_authentication.json ├── plain+2gateways+2portals+2images+isolated+combined.json ├── plain+attributes.json ├── plain+rbd_name.json ├── plain+retries.json ├── plain+uuid.json ├── plain+wwn_generate.json ├── plain.json ├── simple.json ├── tpg+discovery+mutual.json ├── tpg+discovery.json ├── tpg+identified+mutual+discovery+mutual.json ├── tpg+identified.json ├── tpg+mutual+discovery+mutual.json ├── tpg+mutual+discovery.json ├── tpg+mutual.json └── tpg.json ├── sysconfig └── lrbd ├── systemd └── lrbd.service └── test ├── test_acls.py ├── test_auth.py ├── test_authentications.py ├── test_backstores.py ├── test_content.py ├── test_helpers.py ├── test_images.py ├── test_initiatorsettings.py ├── test_iscsi.py ├── test_luns.py ├── test_main.py ├── test_map.py ├── test_pools.py ├── test_portals.py ├── test_portalsecton.py ├── test_sysconfig.py ├── test_targets.py └── test_tpgs.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.pyc 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | 3 | all: rpm 4 | 5 | rpm: tarball 6 | rpmbuild -bb lrbd.spec 7 | 8 | tarball: tests 9 | VERSION=`awk '/^Version/ {print $$2}' lrbd.spec`; \ 10 | git archive --prefix lrbd/ -o ~/rpmbuild/SOURCES/lrbd-$$VERSION.tar.gz HEAD 11 | 12 | tests: 13 | @ln -sf lrbd lrbd.py 14 | @nosetests 15 | @rm -f lrbd.py* 16 | 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lrbd 2 | Simplifies iSCSI management of Ceph RBD images. 3 | 4 | The lrbd utility centrally stores the configuration in Ceph objects and executes the necessary rbd and targetcli commands to apply the stored configuration. 5 | 6 | The tool depends on targetcli which depends on python-rtslib. The original purpose is to support the rbd backstore and is the default option. If your distribution is lacking kernel support or updated packages for targetcli and python-rtslib, the iblock backstore can be used for many configurations. 7 | 8 | ## Quickstart 9 | 10 | For the impatient, follow the instructions for the simplest configuration of one initiator to one gateway to one image. A working Ceph installation is required. 11 | 12 | ### From gateway 13 | 1. Install lrbd 14 | * On SUSE: `# zypper in lrbd` 15 | * On Fedora: `# dnf install lrbd` 16 | * On RHEL 7: `# yum install lrbd` 17 | 2. Create a pool 18 | `# ceph osd pool create swimming 256 256` 19 | * Create an RBD image 20 | `# rbd -p swimming create raft --size 2048` 21 | * Create an initial configuration 22 | `# lrbd -e` 23 | * Replace *archive* with *raft* and *rbd* with *swimming*. Remove the initiator (and the comma from the previous line). Replace the host *igw1* with the result of **uname -n**. Save the file. Run lrbd using an iblock backstore. 24 | `# lrbd -I` 25 | * Inspect with targetcli 26 | `# targetcli ls` 27 | 28 | ### From client 29 | 1. Discover the target. 30 | `# iscsiadm -m discovery -t st -p `*gateway_address* 31 | * Login 32 | `# iscsiadm -m node -p `*gateway_address*` --login` 33 | * Find device 34 | `# multipath -ll` 35 | * Format, write data, read data 36 | * Logout 37 | `# iscsiadm -m node -p `*gateway_address*` --logout` 38 | * Delete discovery cache 39 | `# iscsiadm -m node -o delete` 40 | 41 | ### From gateway 42 | 1. From the gateway, clear the configuration 43 | `# lrbd -C` 44 | * Unmap the RBD images 45 | `# lrbd -u` 46 | * Wipe the configuration from Ceph 47 | `# lrbd -W` 48 | 49 | ## Manual 50 | 51 | See [Wiki](https://github.com/swiftgist/lrbd/wiki) 52 | 53 | ## FAQ 54 | 55 | * What is a gateway? 56 | 57 | The gateway is simply a Linux host that supports iSCSI. This host is providing iSCSI access to another host, a client or initiator, and is mapping Ceph RBD images locally. Any client that cannot use Ceph directly (lack of library support), but supports iSCSI can still use Ceph storage. 58 | 59 | One gateway can support multiple iSCSI targets which is primarily the reason for the distinction. 60 | 61 | * Where should lrbd run? 62 | 63 | For creating or editing the configuration, lrbd can run on any ceph client with proper credentials (e.g. ceph.client.admin.keyring). For applying the configuration, lrbd runs on the host intended to be a gateway. 64 | 65 | * What about configuring multipath? 66 | 67 | Lrbd does not configure multipath on an initiator. See **multipathd**. 68 | -------------------------------------------------------------------------------- /README.migration: -------------------------------------------------------------------------------- 1 | 2 | # Transition from 1.0 to 1.1 3 | 4 | If you have an existing production setup and need to retain the original default behavior, then run the following: 5 | 6 | `# lrbd -m 1.0 > /tmp/lrbd.conf-migrated` 7 | 8 | Inspect the contents. Notice the addition of keywords wwn_generate and rbd_name. Then, apply the configuration. 9 | 10 | `# lrbd -f /tmp/lrbd.conf-migrated` 11 | 12 | Remove disable flag from each gateway. 13 | 14 | `# rm -f /var/lib/misc/lrbd.disabled` 15 | 16 | ### Two new defaults are set for 1.1 These are 17 | 18 | 1. Rbd backstore name: The new default includes the pool name which allows the use of the images with the same name in different pools. The effect changes the name of the backstore. For example, an image named "city" inside of pool "rbd" will appear as 19 | 20 | o- / ..................................................................... [...] 21 | o- backstores .......................................................... [...] | o- rbd ................................................. [2 Storage Objects] 22 | | | o- rbd-city ................................ [/dev/rbd/rbd/city activated] 23 | 24 | from `targetcli ls`. In the original scheme, only the image name is used. 25 | 26 | o- / ..................................................................... [...] 27 | o- backstores .......................................................... [...] | o- rbd ................................................. [2 Storage Objects] 28 | | | o- city .................................... [/dev/rbd/rbd/city activated] 29 | 30 | Add the *rbd_name* keyword to any image that needs the original default. 31 | 32 | 2. Dynamic wwn generation: The new default includes the pool name in addition to the target and image name when generating a hash. This default allows the use of an image in more than one target. To find the current values, run the following: 33 | 34 | `# lrbd -d 2>&1| grep ^uuid:` 35 | 36 | The output will be similar to 37 | 38 | uuid: b93f027b-70f1-3cd5-9f24-a395d7367a54 39 | uuid: f0c61181-ae82-3821-b255-594f5805549c 40 | 41 | Add the *wwn_generate* keyword to any target that needs the original default. 42 | 43 | -------------------------------------------------------------------------------- /invalid/README: -------------------------------------------------------------------------------- 1 | These configurations will fail. The config* will fail on importing (i.e. lrbd -f). The runtime* will fail on applying the configuration (i.e. lrbd) 2 | -------------------------------------------------------------------------------- /invalid/config1: -------------------------------------------------------------------------------- 1 | { 2 | "_target": [ 3 | { 4 | "host": "igw1", 5 | "iqn": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "iqn": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "_auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "tpg", 16 | "discovery": { 17 | "auth": "enable", 18 | "userid": "common2", 19 | "password": "pass1", 20 | "mutual": "enable", 21 | "userid_mutual": "target2", 22 | "password_mutual": "pass2" 23 | }, 24 | "tpg": { 25 | "userid": "common2", 26 | "password": "pass1", 27 | "mutual": "enable", 28 | "userid_mutual": "target2", 29 | "password_mutual": "pass2" 30 | }, 31 | "acls": [ 32 | { 33 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 34 | "userid": "initiator1", 35 | "password": "pass1", 36 | "mutual": "enable", 37 | "userid_mutual": "target1", 38 | "password_mutual": "pass2" 39 | } 40 | ] 41 | }, 42 | { 43 | "host": "igw2", 44 | "authentication": "tpg", 45 | "discovery": { 46 | "auth": "enable", 47 | "userid": "common1", 48 | "password": "pass1", 49 | "mutual": "enable", 50 | "userid_mutual": "target1", 51 | "password_mutual": "pass2" 52 | }, 53 | "tpg": { 54 | "userid": "common1", 55 | "password": "pass1", 56 | "mutual": "enable", 57 | "userid_mutual": "target1", 58 | "password_mutual": "pass2" 59 | }, 60 | "acls": [ 61 | { 62 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 63 | "userid": "initiator1", 64 | "password": "pass3", 65 | "mutual": "enable", 66 | "userid_mutual": "target2", 67 | "password_mutual": "pass4" 68 | }, 69 | { 70 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 71 | "userid": "initiator2", 72 | "password": "pass5", 73 | "mutual": "enable", 74 | "userid_mutual": "target2", 75 | "password_mutual": "pass6" 76 | } 77 | ] 78 | } 79 | ] 80 | } 81 | -------------------------------------------------------------------------------- /invalid/config2: -------------------------------------------------------------------------------- 1 | { 2 | "_target": [ 3 | { 4 | "host": "igw1", 5 | "iqn": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "iqn": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "_auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "tpg", 16 | "discovery": { 17 | "auth": "enable", 18 | "userid": "common2", 19 | "password": "pass1", 20 | "mutual": "enable", 21 | "userid_mutual": "target2", 22 | "password_mutual": "pass2" 23 | }, 24 | "tpg": { 25 | "userid": "common2", 26 | "password": "pass1", 27 | "mutual": "enable", 28 | "userid_mutual": "target2", 29 | "password_mutual": "pass2" 30 | }, 31 | "acls": [ 32 | { 33 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 34 | "userid": "initiator1", 35 | "password": "pass1", 36 | "mutual": "enable", 37 | "userid_mutual": "target1", 38 | "password_mutual": "pass2" 39 | } 40 | ] 41 | }, 42 | { 43 | "host": "igw2", 44 | "authentication": "tpg", 45 | "discovery": { 46 | "auth": "enable", 47 | "userid": "common1", 48 | "password": "pass1", 49 | "mutual": "enable", 50 | "userid_mutual": "target1", 51 | "password_mutual": "pass2" 52 | }, 53 | "tpg": { 54 | "userid": "common1", 55 | "password": "pass1", 56 | "mutual": "enable", 57 | "userid_mutual": "target1", 58 | "password_mutual": "pass2" 59 | }, 60 | "acls": [ 61 | { 62 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 63 | "userid": "initiator1", 64 | "password": "pass3", 65 | "mutual": "enable", 66 | "userid_mutual": "target2", 67 | "password_mutual": "pass4" 68 | }, 69 | { 70 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 71 | "userid": "initiator2", 72 | "password": "pass5", 73 | "mutual": "enable", 74 | "userid_mutual": "target2", 75 | "password_mutual": "pass6" 76 | } 77 | ] 78 | } 79 | ], 80 | "pools": [ 81 | ] 82 | } 83 | -------------------------------------------------------------------------------- /invalid/config3: -------------------------------------------------------------------------------- 1 | { 2 | "_target": [ 3 | { 4 | "host": "igw1", 5 | "iqn": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "iqn": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "_auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "tpg", 16 | "discovery": { 17 | "auth": "enable", 18 | "userid": "common2", 19 | "password": "pass1", 20 | "mutual": "enable", 21 | "userid_mutual": "target2", 22 | "password_mutual": "pass2" 23 | }, 24 | "tpg": { 25 | "userid": "common2", 26 | "password": "pass1", 27 | "mutual": "enable", 28 | "userid_mutual": "target2", 29 | "password_mutual": "pass2" 30 | }, 31 | "acls": [ 32 | { 33 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 34 | "userid": "initiator1", 35 | "password": "pass1", 36 | "mutual": "enable", 37 | "userid_mutual": "target1", 38 | "password_mutual": "pass2" 39 | } 40 | ] 41 | }, 42 | { 43 | "host": "igw2", 44 | "authentication": "tpg", 45 | "discovery": { 46 | "auth": "enable", 47 | "userid": "common1", 48 | "password": "pass1", 49 | "mutual": "enable", 50 | "userid_mutual": "target1", 51 | "password_mutual": "pass2" 52 | }, 53 | "tpg": { 54 | "userid": "common1", 55 | "password": "pass1", 56 | "mutual": "enable", 57 | "userid_mutual": "target1", 58 | "password_mutual": "pass2" 59 | }, 60 | "acls": [ 61 | { 62 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 63 | "userid": "initiator1", 64 | "password": "pass3", 65 | "mutual": "enable", 66 | "userid_mutual": "target2", 67 | "password_mutual": "pass4" 68 | }, 69 | { 70 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 71 | "userid": "initiator2", 72 | "password": "pass5", 73 | "mutual": "enable", 74 | "userid_mutual": "target2", 75 | "password_mutual": "pass6" 76 | } 77 | ] 78 | } 79 | ], 80 | "pools": [ 81 | { 82 | "pool": "rbd" 83 | }, 84 | { 85 | "pool": "car" 86 | }, 87 | { 88 | "pool": "whirl" 89 | } 90 | ] 91 | } 92 | -------------------------------------------------------------------------------- /invalid/config4: -------------------------------------------------------------------------------- 1 | { 2 | "_target": [ 3 | { 4 | "host": "igw1", 5 | "iqn": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "iqn": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "_auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "tpg", 16 | "discovery": { 17 | "auth": "enable", 18 | "userid": "common2", 19 | "password": "pass1", 20 | "mutual": "enable", 21 | "userid_mutual": "target2", 22 | "password_mutual": "pass2" 23 | }, 24 | "tpg": { 25 | "userid": "common2", 26 | "password": "pass1", 27 | "mutual": "enable", 28 | "userid_mutual": "target2", 29 | "password_mutual": "pass2" 30 | }, 31 | "acls": [ 32 | { 33 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 34 | "userid": "initiator1", 35 | "password": "pass1", 36 | "mutual": "enable", 37 | "userid_mutual": "target1", 38 | "password_mutual": "pass2" 39 | } 40 | ] 41 | }, 42 | { 43 | "host": "igw2", 44 | "authentication": "tpg", 45 | "discovery": { 46 | "auth": "enable", 47 | "userid": "common1", 48 | "password": "pass1", 49 | "mutual": "enable", 50 | "userid_mutual": "target1", 51 | "password_mutual": "pass2" 52 | }, 53 | "tpg": { 54 | "userid": "common1", 55 | "password": "pass1", 56 | "mutual": "enable", 57 | "userid_mutual": "target1", 58 | "password_mutual": "pass2" 59 | }, 60 | "acls": [ 61 | { 62 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 63 | "userid": "initiator1", 64 | "password": "pass3", 65 | "mutual": "enable", 66 | "userid_mutual": "target2", 67 | "password_mutual": "pass4" 68 | }, 69 | { 70 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 71 | "userid": "initiator2", 72 | "password": "pass5", 73 | "mutual": "enable", 74 | "userid_mutual": "target2", 75 | "password_mutual": "pass6" 76 | } 77 | ] 78 | } 79 | ], 80 | "pools": [ 81 | { 82 | "pool": "rbd", 83 | "gateways": [ 84 | { 85 | "images": [ 86 | { 87 | "image": "city", 88 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 89 | } 90 | ], 91 | "portals": [ 92 | { 93 | "portal": "172.16.1.16" 94 | }, 95 | { 96 | "portal": "172.16.2.16" 97 | } 98 | ] 99 | }, 100 | { 101 | "images": [ 102 | { 103 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 104 | "image": "writers" 105 | }, 106 | { 107 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 108 | "image": "writers" 109 | }, 110 | { 111 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 112 | "image": "wood" 113 | } 114 | ], 115 | "portals": [ 116 | { 117 | "portal": "172.16.1.17" 118 | }, 119 | { 120 | "portal": "172.16.2.17" 121 | } 122 | ] 123 | } 124 | ] 125 | }, 126 | { 127 | "pool": "car", 128 | "gateways": [ 129 | { 130 | "images": [ 131 | { 132 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 133 | "image": "cement" 134 | } 135 | ], 136 | "portals": [ 137 | { 138 | "portal": "172.16.1.16" 139 | }, 140 | { 141 | "portal": "172.16.2.16" 142 | } 143 | ] 144 | } 145 | ] 146 | }, 147 | { 148 | "pool": "whirl", 149 | "gateways": [ 150 | { 151 | "images": [ 152 | { 153 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 154 | "image": "mental" 155 | } 156 | ], 157 | "portals": [ 158 | { 159 | "portal": "172.16.1.17" 160 | }, 161 | { 162 | "portal": "172.16.2.17" 163 | } 164 | ] 165 | } 166 | ] 167 | } 168 | ] 169 | } 170 | -------------------------------------------------------------------------------- /invalid/config5: -------------------------------------------------------------------------------- 1 | { 2 | "_target": [ 3 | { 4 | "host": "igw1", 5 | "iqn": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "iqn": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "_auth": [ 13 | { 14 | "authentication": "tpg", 15 | "discovery": { 16 | "auth": "enable", 17 | "userid": "common2", 18 | "password": "pass1", 19 | "mutual": "enable", 20 | "userid_mutual": "target2", 21 | "password_mutual": "pass2" 22 | }, 23 | "tpg": { 24 | "userid": "common2", 25 | "password": "pass1", 26 | "mutual": "enable", 27 | "userid_mutual": "target2", 28 | "password_mutual": "pass2" 29 | }, 30 | "acls": [ 31 | { 32 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 33 | "userid": "initiator1", 34 | "password": "pass1", 35 | "mutual": "enable", 36 | "userid_mutual": "target1", 37 | "password_mutual": "pass2" 38 | } 39 | ] 40 | }, 41 | { 42 | "authentication": "tpg", 43 | "discovery": { 44 | "auth": "enable", 45 | "userid": "common1", 46 | "password": "pass1", 47 | "mutual": "enable", 48 | "userid_mutual": "target1", 49 | "password_mutual": "pass2" 50 | }, 51 | "tpg": { 52 | "userid": "common1", 53 | "password": "pass1", 54 | "mutual": "enable", 55 | "userid_mutual": "target1", 56 | "password_mutual": "pass2" 57 | }, 58 | "acls": [ 59 | { 60 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 61 | "userid": "initiator1", 62 | "password": "pass3", 63 | "mutual": "enable", 64 | "userid_mutual": "target2", 65 | "password_mutual": "pass4" 66 | }, 67 | { 68 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 69 | "userid": "initiator2", 70 | "password": "pass5", 71 | "mutual": "enable", 72 | "userid_mutual": "target2", 73 | "password_mutual": "pass6" 74 | } 75 | ] 76 | } 77 | ], 78 | "pools": [ 79 | { 80 | "pool": "rbd", 81 | "gateways": [ 82 | { 83 | "host": "igw1", 84 | "images": [ 85 | { 86 | "image": "city", 87 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 88 | } 89 | ], 90 | "portals": [ 91 | { 92 | "portal": "172.16.1.16" 93 | }, 94 | { 95 | "portal": "172.16.2.16" 96 | } 97 | ] 98 | }, 99 | { 100 | "host": "igw2", 101 | "images": [ 102 | { 103 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 104 | "image": "writers" 105 | }, 106 | { 107 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 108 | "image": "writers" 109 | }, 110 | { 111 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 112 | "image": "wood" 113 | } 114 | ], 115 | "portals": [ 116 | { 117 | "portal": "172.16.1.17" 118 | }, 119 | { 120 | "portal": "172.16.2.17" 121 | } 122 | ] 123 | } 124 | ] 125 | }, 126 | { 127 | "pool": "car", 128 | "gateways": [ 129 | { 130 | "host": "igw1", 131 | "images": [ 132 | { 133 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 134 | "image": "cement" 135 | } 136 | ], 137 | "portals": [ 138 | { 139 | "portal": "172.16.1.16" 140 | }, 141 | { 142 | "portal": "172.16.2.16" 143 | } 144 | ] 145 | } 146 | ] 147 | }, 148 | { 149 | "pool": "whirl", 150 | "gateways": [ 151 | { 152 | "host": "igw2", 153 | "images": [ 154 | { 155 | "iqn": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 156 | "image": "mental" 157 | } 158 | ], 159 | "portals": [ 160 | { 161 | "portal": "172.16.1.17" 162 | }, 163 | { 164 | "portal": "172.16.2.17" 165 | } 166 | ] 167 | } 168 | ] 169 | } 170 | ] 171 | } 172 | -------------------------------------------------------------------------------- /invalid/runtime1: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:generic.x86:sn.abcdefghijk" 6 | } 7 | ], 8 | "auth": [ 9 | { 10 | "host": "igw1", 11 | "authentication": "tpg", 12 | "tpg": { 13 | "userid": "common1", 14 | "password": "pass1" 15 | } 16 | } 17 | ], 18 | "pools": [ 19 | { 20 | "pool": "rbd", 21 | "gateways": [ 22 | { 23 | "host": "igw1", 24 | "tpg": [ 25 | { 26 | "portal": "portal1", 27 | "image": "archive", 28 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 29 | } 30 | ] 31 | } 32 | ] 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /invalid/runtime2: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "tpg", 16 | "tpg": { 17 | "userid": "common2", 18 | "password": "pass1" 19 | } 20 | }, 21 | { 22 | "host": "igw2", 23 | "authentication": "tpg", 24 | "tpg": { 25 | "userid": "common1", 26 | "password": "pass1" 27 | } 28 | } 29 | ], 30 | "portals": [ 31 | { 32 | "name": "portal1", 33 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 34 | }, 35 | { 36 | "name": "portal2", 37 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 38 | } 39 | ], 40 | "pools": [ 41 | { 42 | "pool": "rbd", 43 | "gateways": [ 44 | { 45 | "host": "igw1", 46 | "tpg": [ 47 | { 48 | "portal": "portal1", 49 | "image": "city", 50 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 51 | } 52 | ] 53 | }, 54 | { 55 | "host": "igw2", 56 | "tpg": [ 57 | { 58 | "portal": "portal2", 59 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 60 | "image": "writers" 61 | }, 62 | { 63 | "portal": "portal2", 64 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 65 | "image": "writers" 66 | }, 67 | { 68 | "portal": "portal2", 69 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 70 | "image": "wood" 71 | } 72 | ] 73 | } 74 | ] 75 | }, 76 | { 77 | "pool": "car", 78 | "gateways": [ 79 | { 80 | "host": "igw1", 81 | "tpg": [ 82 | { 83 | "portal": "portal3", 84 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 85 | "image": "cement" 86 | } 87 | ] 88 | } 89 | ] 90 | }, 91 | { 92 | "pool": "whirl", 93 | "gateways": [ 94 | { 95 | "host": "igw2", 96 | "tpg": [ 97 | { 98 | "portal": "portal2", 99 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 100 | "image": "mental" 101 | } 102 | ] 103 | } 104 | ] 105 | } 106 | ] 107 | } 108 | -------------------------------------------------------------------------------- /lrbd.spec: -------------------------------------------------------------------------------- 1 | # 2 | # spec file for package lrbd 3 | # 4 | # Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany. 5 | # 6 | # All modifications and additions to the file contributed by third parties 7 | # remain the property of their copyright owners, unless otherwise agreed 8 | # upon. The license for this file, and modifications and additions to the 9 | # file, is the same license as for the pristine package itself (unless the 10 | # license for the pristine package is not an Open Source License, in which 11 | # case the license is the MIT License). An "Open Source License" is a 12 | # license that conforms to the Open Source Definition (Version 1.9) 13 | # published by the Open Source Initiative. 14 | 15 | # Please submit bugfixes or comments via http://bugs.opensuse.org/ 16 | 17 | # Compat macro for new _fillupdir macro 18 | %if ! %{defined _fillupdir} 19 | %define _fillupdir /var/adm/fillup-templates 20 | %endif 21 | 22 | Summary: lrbd 23 | Name: lrbd 24 | Version: 2.4 25 | Release: 0 26 | License: LGPL-2.1+ 27 | Group: System Environment/Base 28 | Distribution: SUSE 29 | URL: http://bugs.opensuse.org 30 | Source0: lrbd-%{version}.tar.gz 31 | BuildRoot: %{_tmppath}/%{name}-root 32 | BuildArch: noarch 33 | Requires: python3-netifaces 34 | Requires: python3-rados 35 | Requires: python3-rbd 36 | Requires: python3-targetcli-fb 37 | Requires: ceph-common 38 | Summary: Configures iSCSI access to Ceph rbd images 39 | 40 | %description 41 | This utility creates, modifies and retrieves a centralized, configuration from 42 | Ceph for configuring iSCSI access on a host. 43 | 44 | %prep 45 | 46 | 47 | %build 48 | %__tar xvzf %{SOURCE0} 49 | %__rm -f lrbd/man/*.gz 50 | %__gzip lrbd/man/lrbd.* 51 | 52 | %install 53 | %define _samples %{buildroot}%{_docdir}/%{name}/samples 54 | mkdir -p %{buildroot}%{_fillupdir} 55 | mkdir -p %{buildroot}%{_unitdir} 56 | mkdir -p %{buildroot}%{_docdir}/%{name}/samples 57 | mkdir -p %{buildroot}%{_mandir}/man5 58 | mkdir -p %{buildroot}%{_mandir}/man8 59 | mkdir -p %{buildroot}%{_sbindir} 60 | 61 | cd lrbd 62 | install -m 555 lrbd %{buildroot}%{_sbindir} 63 | install -m 644 man/lrbd.conf.5.gz %{buildroot}%{_mandir}/man5 64 | install -m 644 man/lrbd.8.gz %{buildroot}%{_mandir}/man8 65 | 66 | install -m 644 sysconfig/%{name} %{buildroot}%{_fillupdir}/sysconfig.%{name} 67 | install -m 644 systemd/lrbd.service %{buildroot}%{_unitdir} 68 | ln -sf %{_sbindir}/service %{buildroot}%_sbindir/rclrbd 69 | install -m 644 README.migration %{buildroot}%{_docdir}/%{name} 70 | install -m 644 LICENSE %{buildroot}%{_docdir}/%{name} 71 | 72 | install -m 644 samples/acls+discovery.json %{_samples} 73 | install -m 644 samples/acls+discovery+mutual.json %{_samples} 74 | install -m 644 samples/acls.json %{_samples} 75 | install -m 644 samples/acls+settings.json %{_samples} 76 | install -m 644 samples/acls+mutual+discovery.json %{_samples} 77 | install -m 644 samples/acls+mutual+discovery+mutual.json %{_samples} 78 | install -m 644 samples/acls+mutual.json %{_samples} 79 | install -m 644 samples/complete.json %{_samples} 80 | install -m 644 samples/no_authentication+explicit.json %{_samples} 81 | install -m 644 samples/no_authentication.json %{_samples} 82 | install -m 644 samples/plain.json %{_samples} 83 | install -m 644 samples/simple.json %{_samples} 84 | install -m 644 samples/tpg+discovery.json %{_samples} 85 | install -m 644 samples/tpg+discovery+mutual.json %{_samples} 86 | install -m 644 samples/tpg.json %{_samples} 87 | install -m 644 samples/tpg+mutual+discovery.json %{_samples} 88 | install -m 644 samples/tpg+mutual+discovery+mutual.json %{_samples} 89 | install -m 644 samples/tpg+mutual.json %{_samples} 90 | install -m 644 samples/2gateways+2images+no_authentication.json %{_samples} 91 | install -m 644 samples/2gateways+2portals+2images+isolated+no_authentication.json %{_samples} 92 | install -m 644 samples/2gateways+2portals+2images+no_authentication.json %{_samples} 93 | install -m 644 samples/2gateways+2portals+no_authentication.json %{_samples} 94 | install -m 644 samples/2gateways+no_authentication.json %{_samples} 95 | install -m 644 samples/2plain+3gateways+2portals+2images+isolated+no_authentication.json %{_samples} 96 | install -m 644 samples/3gateways+2portals+2images+isolated+no_authentication.json %{_samples} 97 | install -m 644 samples/3gateways+no_authentication.json %{_samples} 98 | install -m 644 samples/plain+2gateways+2portals+2images+isolated+combined.json %{_samples} 99 | install -m 644 samples/2gateways+tpg+identified.json %{_samples} 100 | install -m 644 samples/2gateways+tpg+identified+settings.json %{_samples} 101 | install -m 644 samples/3gateways+tpg+identified.json %{_samples} 102 | install -m 644 samples/3gateways+80targets+no_authentication.json %{_samples} 103 | install -m 644 samples/tpg+identified+mutual+discovery+mutual.json %{_samples} 104 | install -m 644 samples/tpg+identified.json %{_samples} 105 | install -m 644 samples/identified.json %{_samples} 106 | install -m 644 samples/identified+settings.json %{_samples} 107 | install -m 644 samples/2gateways+2images+2targets+no_authentication.json %{_samples} 108 | install -m 644 samples/2gateways+2images+assigned_lun+no_authentication.json %{_samples} 109 | install -m 644 samples/plain+uuid.json %{_samples} 110 | install -m 644 samples/plain+wwn_generate.json %{_samples} 111 | install -m 644 samples/nonstandard_port+no_authentication.json %{_samples} 112 | install -m 644 samples/plain+attributes.json %{_samples} 113 | install -m 644 samples/plain+rbd_name.json %{_samples} 114 | install -m 644 samples/plain+retries.json %{_samples} 115 | install -m 644 samples/README.NEW %{_samples} 116 | 117 | 118 | %pre 119 | if [ "$1" == "2" ] 120 | then 121 | # Upgrade from 1.0 122 | grep -q wwn_generate %{_sbindir}/lrbd 123 | if [ $? -ne 0 ] 124 | then 125 | cat > %{_localstatedir}/lib/misc/lrbd.disabled < /tmp/lrbd.conf-migrated 128 | lrbd -f /tmp/lrbd.conf-migrated 129 | rm -f %{_localstatedir}/lib/misc/lrbd.disabled 130 | 131 | See %{_docdir}/%{name}/README.migration for details. 132 | EOF 133 | fi 134 | fi 135 | %service_add_pre lrbd.service 136 | 137 | %post 138 | %service_add_post lrbd.service 139 | %fillup_and_insserv 140 | 141 | 142 | 143 | %preun 144 | %service_del_preun lrbd.service 145 | 146 | %postun 147 | export DISABLE_RESTART_ON_UPDATE=yes 148 | %service_del_postun lrbd.service 149 | 150 | %clean 151 | rm -rf $RPM_BUILD_ROOT 152 | 153 | %files 154 | %defattr(-,root,root) 155 | %{_fillupdir}/sysconfig.%{name} 156 | %{_sbindir}/lrbd 157 | %{_sbindir}/rclrbd 158 | %{_mandir}/man5/lrbd.conf.5.gz 159 | %{_mandir}/man8/lrbd.8.gz 160 | %{_unitdir}/lrbd.service 161 | %dir %attr(-, root, root) %{_docdir}/%{name} 162 | %dir %attr(-, root, root) %{_docdir}/%{name}/samples 163 | %{_docdir}/%{name}/README.migration 164 | %{_docdir}/%{name}/LICENSE 165 | %{_docdir}/%{name}/samples/* 166 | 167 | %changelog 168 | -------------------------------------------------------------------------------- /man/lrbd.8: -------------------------------------------------------------------------------- 1 | .TH lrbd 8 2 | .SH NAME 3 | lrbd \- configures iSCSI access to Ceph rbd images 4 | .SH SYNOPSIS 5 | .B lrbd [OPTION] 6 | .B ... 7 | .SH DESCRIPTION 8 | .B lrbd 9 | without any options will read the configuration from Ceph and 10 | apply the changes to the host. The configuration is detailed 11 | in 12 | .BR lrbd.conf (5). 13 | Changes are executed via 14 | .BR targetcli (8). 15 | 16 | The options are as follows: 17 | .SH OPTIONS 18 | .PP 19 | \-e, \-\-edit 20 | .RS 4 21 | edit the global configuration. If the EDITOR environment variable is set, uses the specified editor. 22 | .RE 23 | .PP 24 | \-E editor, \-\-edit editor 25 | .RS 4 26 | edit the global configuration with the program specified. 27 | .RE 28 | .PP 29 | \-c name, \-\-config name 30 | .RS 4 31 | sets the object name in Ceph to name. The default is 32 | .IR lrbd.conf 33 | .RE 34 | .PP 35 | \-\-ceph ceph 36 | .RS 4 37 | set the Ceph configuration file. The default is /etc/ceph/ceph.conf. 38 | .RE 39 | .PP 40 | \-H host, \-\-host host 41 | .RS 4 42 | specify the hostname which matches either gethostname() or getfqdn() by default. 43 | .RE 44 | .PP 45 | \-o, \-\-output 46 | .RS 4 47 | display the global configuration 48 | .RE 49 | .PP 50 | \-l, \-\-local 51 | .RS 4 52 | display the host configuration 53 | .RE 54 | .PP 55 | \-f file, \-\-file file 56 | .RS 4 57 | import the configuration from a file 58 | .RE 59 | .PP 60 | \-a file, \-\-add file 61 | .RS 4 62 | add the configuration from a file 63 | .RE 64 | .PP 65 | \-u, \-\-unmap 66 | .RS 4 67 | unmap the rbd images. Images in use will fail to unmap. 68 | .RE 69 | .PP 70 | \-v, \-\-verbose 71 | .RS 4 72 | print INFO messages 73 | .RE 74 | .PP 75 | \-d, \-\-debug 76 | .RS 4 77 | print DEBUG messages 78 | .RE 79 | .PP 80 | \-m migrate, \-\-migrate migrate 81 | .RS 4 82 | outputs migrated configuration to stdout from specified version 83 | .RE 84 | .PP 85 | \-I, \-\-iblock 86 | .RS 4 87 | use an iblock backstore for images, default to rbd 88 | .RE 89 | .PP 90 | \-R, \-\-rbd 91 | .RS 4 92 | use an rbd backstore for images, can override -I 93 | .RE 94 | .PP 95 | \-W, \-\-wipe 96 | .RS 4 97 | remove all configuration objects from all pools. Use with care. 98 | .RE 99 | .PP 100 | \-C, \-\-clear 101 | .RS 4 102 | remove the current targetcli configuration from the host. 103 | .RE 104 | .PP 105 | Some options may be combined, such as \-Cu to first clear the configuration and then unmap the images. 106 | .RE 107 | .SH EXAMPLES 108 | .sp 109 | .RS 4 110 | .ie n \{\ 111 | \h'-04'\(bu\h'+03'\c 112 | .\} 113 | .el \{\ 114 | .sp -1 115 | .IP \(bu 2.3 116 | .\} 117 | Customize a sample configuration and import. 118 | .sp 119 | .if n \{\ 120 | .RS 4 121 | .\} 122 | .nf 123 | $ cp /usr/share/doc/packages/lrbd/samples/tpg.json /tmp 124 | $ vi /tmp/tpg.json 125 | $ lrbd -f /tmp/tpg.json 126 | .fi 127 | .if n \{\ 128 | .sp 129 | .RE 130 | .\} 131 | Edit the current configuration with the editor joe 132 | .sp 133 | .if n \{\ 134 | .RS 4 135 | .\} 136 | .nf 137 | $ lrbd -E joe 138 | .fi 139 | .if n \{\ 140 | .RE 141 | .\} 142 | .sp 143 | .sp 144 | Display the configuration for another host on the current gateway. 145 | .sp 146 | .if n \{\ 147 | .RS 4 148 | .\} 149 | .nf 150 | $ lrbd -H gateway2 -l 151 | .fi 152 | .if n \{\ 153 | .RE 154 | .\} 155 | .sp 156 | .RE 157 | .SH FILES 158 | .I /etc/sysconfig/lrbd 159 | .RS 160 | The environment file for customizing options for the lrbd.service. Any options are automatically included when running at the command line. 161 | .RE 162 | .I /usr/lib/systemd/system/lrbd.service 163 | .RS 164 | The service file to apply the configuration during boot. 165 | .RE 166 | .SH AUTHOR 167 | Eric Jackson 168 | .SH "SEE ALSO" 169 | .BR lrbd.conf (5), 170 | .BR targetcli (8), 171 | -------------------------------------------------------------------------------- /samples/2gateways+2images+2targets+no_authentication.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": [ 3 | { 4 | "authentication": "none", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 6 | }, 7 | { 8 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.second", 9 | "authentication": "tpg", 10 | "tpg": { 11 | "userid": "common2", 12 | "password": "pass1" 13 | } 14 | } 15 | ], 16 | "targets": [ 17 | { 18 | "hosts": [ 19 | { "host": "igw1", "portal": "portal1" }, 20 | { "host": "igw2", "portal": "portal2" } 21 | ], 22 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 23 | }, 24 | { 25 | "hosts": [ 26 | { "host": "igw1", "portal": "portal3" }, 27 | { "host": "igw2", "portal": "portal4" } 28 | ], 29 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.second" 30 | } 31 | ], 32 | "portals": [ 33 | { 34 | "name": "portal1", 35 | "addresses": [ "172.16.11.16" ] 36 | }, 37 | { 38 | "name": "portal2", 39 | "addresses": [ "172.16.11.17" ] 40 | }, 41 | { 42 | "name": "portal3", 43 | "addresses": [ "172.16.12.16" ] 44 | }, 45 | { 46 | "name": "portal4", 47 | "addresses": [ "172.16.12.17" ] 48 | } 49 | ], 50 | "pools": [ 51 | { 52 | "pool": "rbd", 53 | "gateways": [ 54 | { 55 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant", 56 | "tpg": [ 57 | { 58 | "image": "city" 59 | }, 60 | { 61 | "image": "wood" 62 | } 63 | ] 64 | }, 65 | { 66 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.second", 67 | "tpg": [ 68 | { 69 | "image": "city" 70 | }, 71 | { 72 | "image": "wood" 73 | } 74 | ] 75 | } 76 | ] 77 | } 78 | ] 79 | } 80 | -------------------------------------------------------------------------------- /samples/2gateways+2images+assigned_lun+no_authentication.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": [ 3 | { 4 | "authentication": "none", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 6 | } 7 | ], 8 | "targets": [ 9 | { 10 | "hosts": [ 11 | { "host": "igw1", "portal": "portal1" }, 12 | { "host": "igw2", "portal": "portal2" } 13 | ], 14 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 15 | } 16 | ], 17 | "portals": [ 18 | { 19 | "name": "portal1", 20 | "addresses": [ "172.16.1.16" ] 21 | }, 22 | { 23 | "name": "portal2", 24 | "addresses": [ "172.16.1.17" ] 25 | } 26 | ], 27 | "pools": [ 28 | { 29 | "pool": "rbd", 30 | "gateways": [ 31 | { 32 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant", 33 | "tpg": [ 34 | { 35 | "image": "city", 36 | "lun": "2" 37 | }, 38 | { 39 | "image": "wood", 40 | "lun": "0" 41 | }, 42 | { 43 | "image": "writers" 44 | } 45 | ] 46 | } 47 | ] 48 | } 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /samples/2gateways+2images+no_authentication.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": [ 3 | { 4 | "authentication": "none", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 6 | } 7 | ], 8 | "targets": [ 9 | { 10 | "hosts": [ 11 | { "host": "igw1", "portal": "portal1" }, 12 | { "host": "igw2", "portal": "portal2" } 13 | ], 14 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 15 | } 16 | ], 17 | "portals": [ 18 | { 19 | "name": "portal1", 20 | "addresses": [ "172.16.1.16" ] 21 | }, 22 | { 23 | "name": "portal2", 24 | "addresses": [ "172.16.1.17" ] 25 | } 26 | ], 27 | "pools": [ 28 | { 29 | "pool": "rbd", 30 | "gateways": [ 31 | { 32 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant", 33 | "tpg": [ 34 | { 35 | "image": "city" 36 | }, 37 | { 38 | "image": "wood" 39 | } 40 | ] 41 | } 42 | ] 43 | } 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /samples/2gateways+2portals+2images+isolated+no_authentication.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": [ 3 | { 4 | "authentication": "none", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 6 | } 7 | ], 8 | "targets": [ 9 | { 10 | "hosts": [ 11 | { "host": "igw1", "portal": "portal1" }, 12 | { "host": "igw1", "portal": "portal2" }, 13 | { "host": "igw2", "portal": "portal3" }, 14 | { "host": "igw2", "portal": "portal4" } 15 | ], 16 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 17 | } 18 | ], 19 | "portals": [ 20 | { 21 | "name": "portal1", 22 | "addresses": [ "172.16.1.16" ] 23 | }, 24 | { 25 | "name": "portal2", 26 | "addresses": [ "172.16.1.17" ] 27 | }, 28 | { 29 | "name": "portal3", 30 | "addresses": [ "172.16.2.16" ] 31 | }, 32 | { 33 | "name": "portal4", 34 | "addresses": [ "172.16.2.17" ] 35 | } 36 | ], 37 | "pools": [ 38 | { 39 | "pool": "rbd", 40 | "gateways": [ 41 | { 42 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant", 43 | "tpg": [ 44 | { 45 | "image": "city" 46 | }, 47 | { 48 | "image": "wood" 49 | } 50 | ] 51 | } 52 | ] 53 | } 54 | ] 55 | } 56 | -------------------------------------------------------------------------------- /samples/2gateways+2portals+2images+no_authentication.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": [ 3 | { 4 | "authentication": "none", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 6 | } 7 | ], 8 | "targets": [ 9 | { 10 | "hosts": [ 11 | { "host": "igw1", "portal": "portal3" }, 12 | { "host": "igw2", "portal": "portal4" } 13 | ], 14 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 15 | } 16 | ], 17 | "portals": [ 18 | { 19 | "name": "portal3", 20 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 21 | }, 22 | { 23 | "name": "portal4", 24 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 25 | } 26 | ], 27 | "pools": [ 28 | { 29 | "pool": "rbd", 30 | "gateways": [ 31 | { 32 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant", 33 | "tpg": [ 34 | { 35 | "image": "city" 36 | }, 37 | { 38 | "image": "wood" 39 | } 40 | ] 41 | } 42 | ] 43 | } 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /samples/2gateways+2portals+no_authentication.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": [ 3 | { 4 | "authentication": "none", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 6 | } 7 | ], 8 | "targets": [ 9 | { 10 | "hosts": [ 11 | { "host": "igw1", "portal": "portal3" }, 12 | { "host": "igw2", "portal": "portal4" } 13 | ], 14 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 15 | } 16 | ], 17 | "portals": [ 18 | { 19 | "name": "portal3", 20 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 21 | }, 22 | { 23 | "name": "portal4", 24 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 25 | } 26 | ], 27 | "pools": [ 28 | { 29 | "pool": "rbd", 30 | "gateways": [ 31 | { 32 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant", 33 | "tpg": [ 34 | { 35 | "image": "city" 36 | } 37 | ] 38 | } 39 | ] 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /samples/2gateways+no_authentication.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": [ 3 | { 4 | "authentication": "none", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 6 | } 7 | ], 8 | "targets": [ 9 | { 10 | "hosts": [ 11 | { "host": "igw1", "portal": "portal1" }, 12 | { "host": "igw2", "portal": "portal2" } 13 | ], 14 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 15 | } 16 | ], 17 | "portals": [ 18 | { 19 | "name": "portal1", 20 | "addresses": [ "172.16.1.16"] 21 | }, 22 | { 23 | "name": "portal2", 24 | "addresses": [ "172.16.1.17" ] 25 | } 26 | ], 27 | "pools": [ 28 | { 29 | "pool": "rbd", 30 | "gateways": [ 31 | { 32 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant", 33 | "tpg": [ 34 | { 35 | "image": "city" 36 | } 37 | ] 38 | } 39 | ] 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /samples/2gateways+tpg+identified+settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": [ 3 | { 4 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant", 5 | "authentication": "tpg+identified", 6 | "tpg": { 7 | "userid": "common2", 8 | "password": "pass1" 9 | }, 10 | "identified": [ 11 | { 12 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 13 | "attrib_dataout_timeout": "3", 14 | "attrib_dataout_timeout_retries": "5", 15 | "attrib_default_erl": "0", 16 | "attrib_nopin_response_timeout": "30", 17 | "attrib_nopin_timeout": "15", 18 | "attrib_random_datain_pdu_offsets": "0", 19 | "attrib_random_datain_seq_offsets": "0", 20 | "attrib_random_r2t_offsets": "0", 21 | "param_DataPDUInOrder": "1", 22 | "param_DataSequenceInOrder": "1", 23 | "param_DefaultTime2Retain": "0", 24 | "param_DefaultTime2Wait": "2", 25 | "param_ErrorRecoveryLevel": "0", 26 | "param_FirstBurstLength": "65536", 27 | "param_ImmediateData": "1", 28 | "param_InitialR2T": "1", 29 | "param_MaxBurstLength": "262144", 30 | "param_MaxConnections": "1", 31 | "param_MaxOutstandingR2T": "1" 32 | } 33 | ] 34 | } 35 | ], 36 | "targets": [ 37 | { 38 | "hosts": [ 39 | { "host": "igw1", "portal": "portal1" }, 40 | { "host": "igw2", "portal": "portal2" } 41 | ], 42 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 43 | } 44 | ], 45 | "portals": [ 46 | { 47 | "name": "portal1", 48 | "addresses": [ "172.16.1.16"] 49 | }, 50 | { 51 | "name": "portal2", 52 | "addresses": [ "172.16.1.17" ] 53 | } 54 | ], 55 | "pools": [ 56 | { 57 | "pool": "rbd", 58 | "gateways": [ 59 | { 60 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant", 61 | "tpg": [ 62 | { 63 | "image": "city", 64 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 65 | } 66 | ] 67 | } 68 | ] 69 | } 70 | ] 71 | } 72 | -------------------------------------------------------------------------------- /samples/2gateways+tpg+identified.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": [ 3 | { 4 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant", 5 | "authentication": "tpg+identified", 6 | "tpg": { 7 | "userid": "common2", 8 | "password": "pass1" 9 | } 10 | } 11 | ], 12 | "targets": [ 13 | { 14 | "hosts": [ 15 | { "host": "igw1", "portal": "portal1" }, 16 | { "host": "igw2", "portal": "portal2" } 17 | ], 18 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 19 | } 20 | ], 21 | "portals": [ 22 | { 23 | "name": "portal1", 24 | "addresses": [ "172.16.1.16"] 25 | }, 26 | { 27 | "name": "portal2", 28 | "addresses": [ "172.16.1.17" ] 29 | } 30 | ], 31 | "pools": [ 32 | { 33 | "pool": "rbd", 34 | "gateways": [ 35 | { 36 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant", 37 | "tpg": [ 38 | { 39 | "image": "city", 40 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 41 | } 42 | ] 43 | } 44 | ] 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /samples/2plain+3gateways+2portals+2images+isolated+no_authentication.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": [ 3 | { 4 | "authentication": "none", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 6 | }, 7 | { 8 | "authentication": "none", 9 | "host": "igw1" 10 | }, 11 | { 12 | "authentication": "none", 13 | "host": "igw2" 14 | } 15 | ], 16 | "targets": [ 17 | { 18 | "host": "igw1", 19 | "target": "iqn.2003-01.org.linux-iscsi:generic.x86:sn.abcdefghijk" 20 | }, 21 | { 22 | "host": "igw2", 23 | "target": "iqn.2003-01.org.linux-iscsi:generic.x86:sn.lmnopqrstuv" 24 | }, 25 | { 26 | "hosts": [ 27 | { "host": "igw1", "portal": "portal1" }, 28 | { "host": "igw1", "portal": "portal2" }, 29 | { "host": "igw2", "portal": "portal3" }, 30 | { "host": "igw2", "portal": "portal4" }, 31 | { "host": "igw3", "portal": "portal5" }, 32 | { "host": "igw3", "portal": "portal6" } 33 | ], 34 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 35 | } 36 | ], 37 | "portals": [ 38 | { 39 | "name": "portal1", 40 | "addresses": [ "172.16.1.16" ] 41 | }, 42 | { 43 | "name": "portal2", 44 | "addresses": [ "172.16.2.16" ] 45 | }, 46 | { 47 | "name": "portal3", 48 | "addresses": [ "172.16.1.17" ] 49 | }, 50 | { 51 | "name": "portal4", 52 | "addresses": [ "172.16.2.17" ] 53 | }, 54 | { 55 | "name": "portal5", 56 | "addresses": [ "172.16.1.18" ] 57 | }, 58 | { 59 | "name": "portal6", 60 | "addresses": [ "172.16.2.18" ] 61 | }, 62 | { 63 | "name": "portal7", 64 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 65 | } 66 | ], 67 | "pools": [ 68 | { 69 | "pool": "rbd", 70 | "gateways": [ 71 | { 72 | "host": "igw1", 73 | "tpg": [ 74 | { 75 | "portal": "portal1", 76 | "image": "archive" 77 | } 78 | ] 79 | }, 80 | { 81 | "host": "igw2", 82 | "tpg": [ 83 | { 84 | "portal": "portal7", 85 | "image": "writers" 86 | } 87 | ] 88 | }, 89 | { 90 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant", 91 | "tpg": [ 92 | { 93 | "image": "city" 94 | }, 95 | { 96 | "image": "wood" 97 | } 98 | ] 99 | } 100 | ] 101 | } 102 | ] 103 | } 104 | -------------------------------------------------------------------------------- /samples/3gateways+2portals+2images+isolated+no_authentication.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": [ 3 | { 4 | "authentication": "none", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 6 | } 7 | ], 8 | "targets": [ 9 | { 10 | "hosts": [ 11 | { "host": "igw1", "portal": "portal1" }, 12 | { "host": "igw1", "portal": "portal2" }, 13 | { "host": "igw2", "portal": "portal3" }, 14 | { "host": "igw2", "portal": "portal4" }, 15 | { "host": "igw3", "portal": "portal5" }, 16 | { "host": "igw3", "portal": "portal6" } 17 | ], 18 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 19 | } 20 | ], 21 | "portals": [ 22 | { 23 | "name": "portal1", 24 | "addresses": [ "172.16.1.16" ] 25 | }, 26 | { 27 | "name": "portal2", 28 | "addresses": [ "172.16.2.16" ] 29 | }, 30 | { 31 | "name": "portal3", 32 | "addresses": [ "172.16.1.17" ] 33 | }, 34 | { 35 | "name": "portal4", 36 | "addresses": [ "172.16.2.17" ] 37 | }, 38 | { 39 | "name": "portal5", 40 | "addresses": [ "172.16.1.18" ] 41 | }, 42 | { 43 | "name": "portal6", 44 | "addresses": [ "172.16.2.18" ] 45 | } 46 | ], 47 | "pools": [ 48 | { 49 | "pool": "rbd", 50 | "gateways": [ 51 | { 52 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant", 53 | "tpg": [ 54 | { 55 | "image": "city" 56 | }, 57 | { 58 | "image": "wood" 59 | } 60 | ] 61 | } 62 | ] 63 | } 64 | ] 65 | } 66 | -------------------------------------------------------------------------------- /samples/3gateways+no_authentication.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": [ 3 | { 4 | "authentication": "none", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 6 | } 7 | ], 8 | "targets": [ 9 | { 10 | "hosts": [ 11 | { "host": "igw1", "portal": "portal1" }, 12 | { "host": "igw2", "portal": "portal2" }, 13 | { "host": "igw3", "portal": "portal3" } 14 | ], 15 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 16 | } 17 | ], 18 | "portals": [ 19 | { 20 | "name": "portal1", 21 | "addresses": [ "172.16.1.16"] 22 | }, 23 | { 24 | "name": "portal2", 25 | "addresses": [ "172.16.1.17" ] 26 | }, 27 | { 28 | "name": "portal3", 29 | "addresses": [ "172.16.1.18" ] 30 | } 31 | ], 32 | "pools": [ 33 | { 34 | "pool": "rbd", 35 | "gateways": [ 36 | { 37 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant", 38 | "tpg": [ 39 | { 40 | "image": "city" 41 | } 42 | ] 43 | } 44 | ] 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /samples/3gateways+tpg+identified.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": [ 3 | { 4 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant", 5 | "authentication": "tpg+identified", 6 | "tpg": { 7 | "userid": "common2", 8 | "password": "pass1" 9 | } 10 | } 11 | ], 12 | "targets": [ 13 | { 14 | "hosts": [ 15 | { "host": "igw1", "portal": "portal1" }, 16 | { "host": "igw2", "portal": "portal2" }, 17 | { "host": "igw3", "portal": "portal3" } 18 | ], 19 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 20 | } 21 | ], 22 | "portals": [ 23 | { 24 | "name": "portal1", 25 | "addresses": [ "172.16.1.16"] 26 | }, 27 | { 28 | "name": "portal2", 29 | "addresses": [ "172.16.1.17" ] 30 | }, 31 | { 32 | "name": "portal3", 33 | "addresses": [ "172.16.1.18" ] 34 | } 35 | ], 36 | "pools": [ 37 | { 38 | "pool": "rbd", 39 | "gateways": [ 40 | { 41 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant", 42 | "tpg": [ 43 | { 44 | "image": "city", 45 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 46 | } 47 | ] 48 | } 49 | ] 50 | } 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /samples/README.NEW: -------------------------------------------------------------------------------- 1 | 2 | Four new requested features have been added. 3 | 4 | 1) The generation of the WWN for the vpd_unit_serial number uses the python call uuid.uuid3. The original passed argument is the concatenation of target and image name. The new scheme includes the pool name. See plain+wwn_generate.json to keep the original behavior. 5 | 6 | 2) If the automatic generation of the WWN is detrimental to your site, you may now hardcode a value. For instance, if you wish to rename a target or image and retain the same uuid, set this value. See plain+uuid.json. (To quickly see the current values, run 'lrbd -d 2>&1 | grep uuid:') 7 | 8 | 3) The dynamic assignment of sites with many LUNs removed and added regularly may require rescans and remapping. The value of the LUNs may now be hardcoded. Unassigned LUNs will still be allocated dynamically. See 2gateways+2images+assigned_lun+no_authentication.json. 9 | 10 | 4) Sharing the same image from the same pool to two different targets on the same gateway has not been supported. This is a first attempt. Consider this extremely *experimental*. See 2gateways+2images+2targets+no_authentication.json. The primary purpose is to have two different authentication strategies for the same image. 11 | -------------------------------------------------------------------------------- /samples/acls+discovery+mutual.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "acls", 16 | "discovery": { 17 | "auth": "enable", 18 | "userid": "common2", 19 | "password": "pass1", 20 | "mutual": "enable", 21 | "userid_mutual": "target2", 22 | "password_mutual": "pass2" 23 | }, 24 | "acls": [ 25 | { 26 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 27 | "userid": "initiator1", 28 | "password": "pass1" 29 | } 30 | ] 31 | }, 32 | { 33 | "host": "igw2", 34 | "authentication": "acls", 35 | "discovery": { 36 | "auth": "enable", 37 | "userid": "common1", 38 | "password": "pass1", 39 | "mutual": "enable", 40 | "userid_mutual": "target1", 41 | "password_mutual": "pass2" 42 | }, 43 | "acls": [ 44 | { 45 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 46 | "userid": "initiator1", 47 | "password": "pass3" 48 | }, 49 | { 50 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 51 | "userid": "initiator2", 52 | "password": "pass5" 53 | } 54 | ] 55 | } 56 | ], 57 | "portals": [ 58 | { 59 | "name": "portal1", 60 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 61 | }, 62 | { 63 | "name": "portal2", 64 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 65 | } 66 | ], 67 | "pools": [ 68 | { 69 | "pool": "rbd", 70 | "gateways": [ 71 | { 72 | "host": "igw1", 73 | "tpg": [ 74 | { 75 | "image": "city", 76 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 77 | "portal": "portal1" 78 | } 79 | ] 80 | }, 81 | { 82 | "host": "igw2", 83 | "tpg": [ 84 | { 85 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 86 | "image": "writers", 87 | "portal": "portal2" 88 | }, 89 | { 90 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 91 | "image": "writers", 92 | "portal": "portal2" 93 | }, 94 | { 95 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 96 | "image": "wood", 97 | "portal": "portal2" 98 | } 99 | ] 100 | } 101 | ] 102 | }, 103 | { 104 | "pool": "car", 105 | "gateways": [ 106 | { 107 | "host": "igw1", 108 | "tpg": [ 109 | { 110 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 111 | "image": "cement", 112 | "portal": "portal1" 113 | } 114 | ] 115 | } 116 | ] 117 | }, 118 | { 119 | "pool": "whirl", 120 | "gateways": [ 121 | { 122 | "host": "igw2", 123 | "tpg": [ 124 | { 125 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 126 | "image": "cheese", 127 | "portal": "portal2" 128 | } 129 | ] 130 | } 131 | ] 132 | } 133 | ] 134 | } 135 | -------------------------------------------------------------------------------- /samples/acls+discovery.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "acls", 16 | "discovery": { 17 | "auth": "enable", 18 | "userid": "common2", 19 | "password": "pass1" 20 | }, 21 | "acls": [ 22 | { 23 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 24 | "userid": "initiator1", 25 | "password": "pass1" 26 | } 27 | ] 28 | }, 29 | { 30 | "host": "igw2", 31 | "authentication": "acls", 32 | "discovery": { 33 | "auth": "enable", 34 | "userid": "common1", 35 | "password": "pass1" 36 | }, 37 | "acls": [ 38 | { 39 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 40 | "userid": "initiator1", 41 | "password": "pass3" 42 | }, 43 | { 44 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 45 | "userid": "initiator2", 46 | "password": "pass5" 47 | } 48 | ] 49 | } 50 | ], 51 | "portals": [ 52 | { 53 | "name": "portal1", 54 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 55 | }, 56 | { 57 | "name": "portal2", 58 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 59 | } 60 | ], 61 | "pools": [ 62 | { 63 | "pool": "rbd", 64 | "gateways": [ 65 | { 66 | "host": "igw1", 67 | "tpg": [ 68 | { 69 | "portal": "portal1", 70 | "image": "city", 71 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 72 | } 73 | ] 74 | }, 75 | { 76 | "host": "igw2", 77 | "tpg": [ 78 | { 79 | "portal": "portal2", 80 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 81 | "image": "writers" 82 | }, 83 | { 84 | "portal": "portal2", 85 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 86 | "image": "writers" 87 | }, 88 | { 89 | "portal": "portal2", 90 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 91 | "image": "wood" 92 | } 93 | ] 94 | } 95 | ] 96 | }, 97 | { 98 | "pool": "car", 99 | "gateways": [ 100 | { 101 | "host": "igw1", 102 | "tpg": [ 103 | { 104 | "portal": "portal1", 105 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 106 | "image": "cement" 107 | } 108 | ] 109 | } 110 | ] 111 | }, 112 | { 113 | "pool": "whirl", 114 | "gateways": [ 115 | { 116 | "host": "igw2", 117 | "tpg": [ 118 | { 119 | "portal": "portal2", 120 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 121 | "image": "cheese" 122 | } 123 | ] 124 | } 125 | ] 126 | } 127 | ] 128 | } 129 | -------------------------------------------------------------------------------- /samples/acls+mutual+discovery+mutual.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "acls", 16 | "discovery": { 17 | "auth": "enable", 18 | "userid": "common2", 19 | "password": "pass1", 20 | "mutual": "enable", 21 | "userid_mutual": "target2", 22 | "password_mutual": "pass2" 23 | }, 24 | "acls": [ 25 | { 26 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 27 | "userid": "initiator1", 28 | "password": "pass1", 29 | "mutual": "enable", 30 | "userid_mutual": "target1", 31 | "password_mutual": "pass2" 32 | } 33 | ] 34 | }, 35 | { 36 | "host": "igw2", 37 | "authentication": "acls", 38 | "discovery": { 39 | "auth": "enable", 40 | "userid": "common1", 41 | "password": "pass1", 42 | "mutual": "enable", 43 | "userid_mutual": "target1", 44 | "password_mutual": "pass2" 45 | }, 46 | "acls": [ 47 | { 48 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 49 | "userid": "initiator1", 50 | "password": "pass3", 51 | "mutual": "enable", 52 | "userid_mutual": "target2", 53 | "password_mutual": "pass4" 54 | }, 55 | { 56 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 57 | "userid": "initiator2", 58 | "password": "pass5", 59 | "mutual": "enable", 60 | "userid_mutual": "target2", 61 | "password_mutual": "pass6" 62 | } 63 | ] 64 | } 65 | ], 66 | "portals": [ 67 | { 68 | "name": "portal1", 69 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 70 | }, 71 | { 72 | "name": "portal2", 73 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 74 | } 75 | ], 76 | "pools": [ 77 | { 78 | "pool": "rbd", 79 | "gateways": [ 80 | { 81 | "host": "igw1", 82 | "tpg": [ 83 | { 84 | "portal": "portal1", 85 | "image": "city", 86 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 87 | } 88 | ] 89 | }, 90 | { 91 | "host": "igw2", 92 | "tpg": [ 93 | { 94 | "portal": "portal2", 95 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 96 | "image": "writers" 97 | }, 98 | { 99 | "portal": "portal2", 100 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 101 | "image": "writers" 102 | }, 103 | { 104 | "portal": "portal2", 105 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 106 | "image": "wood" 107 | } 108 | ] 109 | } 110 | ] 111 | }, 112 | { 113 | "pool": "car", 114 | "gateways": [ 115 | { 116 | "host": "igw1", 117 | "tpg": [ 118 | { 119 | "portal": "portal1", 120 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 121 | "image": "cement" 122 | } 123 | ] 124 | } 125 | ] 126 | }, 127 | { 128 | "pool": "whirl", 129 | "gateways": [ 130 | { 131 | "host": "igw2", 132 | "tpg": [ 133 | { 134 | "portal": "portal2", 135 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 136 | "image": "cheese" 137 | } 138 | ] 139 | } 140 | ] 141 | } 142 | ] 143 | } 144 | -------------------------------------------------------------------------------- /samples/acls+mutual+discovery.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "acls", 16 | "discovery": { 17 | "auth": "enable", 18 | "userid": "common2", 19 | "password": "pass1" 20 | }, 21 | "acls": [ 22 | { 23 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 24 | "userid": "initiator1", 25 | "password": "pass1", 26 | "mutual": "enable", 27 | "userid_mutual": "target1", 28 | "password_mutual": "pass2" 29 | } 30 | ] 31 | }, 32 | { 33 | "host": "igw2", 34 | "authentication": "acls", 35 | "discovery": { 36 | "auth": "enable", 37 | "userid": "common1", 38 | "password": "pass1" 39 | }, 40 | "acls": [ 41 | { 42 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 43 | "userid": "initiator1", 44 | "password": "pass3", 45 | "mutual": "enable", 46 | "userid_mutual": "target2", 47 | "password_mutual": "pass4" 48 | }, 49 | { 50 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 51 | "userid": "initiator2", 52 | "password": "pass5", 53 | "mutual": "enable", 54 | "userid_mutual": "target2", 55 | "password_mutual": "pass6" 56 | } 57 | ] 58 | } 59 | ], 60 | "portals": [ 61 | { 62 | "name": "portal1", 63 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 64 | }, 65 | { 66 | "name": "portal2", 67 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 68 | } 69 | ], 70 | "pools": [ 71 | { 72 | "pool": "rbd", 73 | "gateways": [ 74 | { 75 | "host": "igw1", 76 | "tpg": [ 77 | { 78 | "portal": "portal1", 79 | "image": "city", 80 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 81 | } 82 | ] 83 | }, 84 | { 85 | "host": "igw2", 86 | "tpg": [ 87 | { 88 | "portal": "portal2", 89 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 90 | "image": "writers" 91 | }, 92 | { 93 | "portal": "portal2", 94 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 95 | "image": "writers" 96 | }, 97 | { 98 | "portal": "portal2", 99 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 100 | "image": "wood" 101 | } 102 | ] 103 | } 104 | ] 105 | }, 106 | { 107 | "pool": "car", 108 | "gateways": [ 109 | { 110 | "host": "igw1", 111 | "tpg": [ 112 | { 113 | "portal": "portal1", 114 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 115 | "image": "cement" 116 | } 117 | ] 118 | } 119 | ] 120 | }, 121 | { 122 | "pool": "whirl", 123 | "gateways": [ 124 | { 125 | "host": "igw2", 126 | "tpg": [ 127 | { 128 | "portal": "portal2", 129 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 130 | "image": "cheese" 131 | } 132 | ] 133 | } 134 | ] 135 | } 136 | ] 137 | } 138 | -------------------------------------------------------------------------------- /samples/acls+mutual.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "acls", 16 | "acls": [ 17 | { 18 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 19 | "userid": "initiator1", 20 | "password": "pass1", 21 | "mutual": "enable", 22 | "userid_mutual": "target1", 23 | "password_mutual": "pass2" 24 | } 25 | ] 26 | }, 27 | { 28 | "host": "igw2", 29 | "authentication": "acls", 30 | "acls": [ 31 | { 32 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 33 | "userid": "initiator1", 34 | "password": "pass3", 35 | "mutual": "enable", 36 | "userid_mutual": "target2", 37 | "password_mutual": "pass4" 38 | }, 39 | { 40 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 41 | "userid": "initiator2", 42 | "password": "pass5", 43 | "mutual": "enable", 44 | "userid_mutual": "target2", 45 | "password_mutual": "pass6" 46 | } 47 | ] 48 | } 49 | ], 50 | "portals": [ 51 | { 52 | "name": "portal1", 53 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 54 | }, 55 | { 56 | "name": "portal2", 57 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 58 | } 59 | ], 60 | "pools": [ 61 | { 62 | "pool": "rbd", 63 | "gateways": [ 64 | { 65 | "host": "igw1", 66 | "tpg": [ 67 | { 68 | "portal": "portal1", 69 | "image": "city", 70 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 71 | } 72 | ] 73 | }, 74 | { 75 | "host": "igw2", 76 | "tpg": [ 77 | { 78 | "portal": "portal2", 79 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 80 | "image": "writers" 81 | }, 82 | { 83 | "portal": "portal2", 84 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 85 | "image": "writers" 86 | }, 87 | { 88 | "portal": "portal2", 89 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 90 | "image": "wood" 91 | } 92 | ] 93 | } 94 | ] 95 | }, 96 | { 97 | "pool": "car", 98 | "gateways": [ 99 | { 100 | "host": "igw1", 101 | "tpg": [ 102 | { 103 | "portal": "portal1", 104 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 105 | "image": "cement" 106 | } 107 | ] 108 | } 109 | ] 110 | }, 111 | { 112 | "pool": "whirl", 113 | "gateways": [ 114 | { 115 | "host": "igw2", 116 | "tpg": [ 117 | { 118 | "portal": "portal2", 119 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 120 | "image": "cheese" 121 | } 122 | ] 123 | } 124 | ] 125 | } 126 | ] 127 | } 128 | -------------------------------------------------------------------------------- /samples/acls+settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "acls", 16 | "acls": [ 17 | { 18 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 19 | "userid": "initiator1", 20 | "password": "pass1", 21 | "attrib_dataout_timeout": "3", 22 | "attrib_dataout_timeout_retries": "5", 23 | "attrib_default_erl": "0", 24 | "attrib_nopin_response_timeout": "30", 25 | "attrib_nopin_timeout": "15", 26 | "attrib_random_datain_pdu_offsets": "0", 27 | "attrib_random_datain_seq_offsets": "0", 28 | "attrib_random_r2t_offsets": "0", 29 | "param_DataPDUInOrder": "1", 30 | "param_DataSequenceInOrder": "1", 31 | "param_DefaultTime2Retain": "0", 32 | "param_DefaultTime2Wait": "2", 33 | "param_ErrorRecoveryLevel": "0", 34 | "param_FirstBurstLength": "65536", 35 | "param_ImmediateData": "1", 36 | "param_InitialR2T": "1", 37 | "param_MaxBurstLength": "262144", 38 | "param_MaxConnections": "1", 39 | "param_MaxOutstandingR2T": "1" 40 | } 41 | ] 42 | }, 43 | { 44 | "host": "igw2", 45 | "authentication": "acls", 46 | "acls": [ 47 | { 48 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 49 | "userid": "initiator1", 50 | "password": "pass1", 51 | "attrib_dataout_timeout": "3", 52 | "attrib_dataout_timeout_retries": "5", 53 | "attrib_default_erl": "0", 54 | "attrib_nopin_response_timeout": "30", 55 | "attrib_nopin_timeout": "15", 56 | "attrib_random_datain_pdu_offsets": "0", 57 | "attrib_random_datain_seq_offsets": "0", 58 | "attrib_random_r2t_offsets": "0", 59 | "param_DataPDUInOrder": "1", 60 | "param_DataSequenceInOrder": "1", 61 | "param_DefaultTime2Retain": "0", 62 | "param_DefaultTime2Wait": "2", 63 | "param_ErrorRecoveryLevel": "0", 64 | "param_FirstBurstLength": "65536", 65 | "param_ImmediateData": "1", 66 | "param_InitialR2T": "1", 67 | "param_MaxBurstLength": "262144", 68 | "param_MaxConnections": "1", 69 | "param_MaxOutstandingR2T": "1" 70 | }, 71 | { 72 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 73 | "userid": "initiator2", 74 | "password": "pass5", 75 | "attrib_dataout_timeout": "3", 76 | "attrib_dataout_timeout_retries": "5", 77 | "attrib_default_erl": "0", 78 | "attrib_nopin_response_timeout": "30", 79 | "attrib_nopin_timeout": "15", 80 | "attrib_random_datain_pdu_offsets": "0", 81 | "attrib_random_datain_seq_offsets": "0", 82 | "attrib_random_r2t_offsets": "0", 83 | "param_DataPDUInOrder": "1", 84 | "param_DataSequenceInOrder": "1", 85 | "param_DefaultTime2Retain": "0", 86 | "param_DefaultTime2Wait": "2", 87 | "param_ErrorRecoveryLevel": "0", 88 | "param_FirstBurstLength": "65536", 89 | "param_ImmediateData": "1", 90 | "param_InitialR2T": "1", 91 | "param_MaxBurstLength": "262144", 92 | "param_MaxConnections": "1", 93 | "param_MaxOutstandingR2T": "1" 94 | } 95 | ] 96 | } 97 | ], 98 | "portals": [ 99 | { 100 | "name": "portal1", 101 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 102 | }, 103 | { 104 | "name": "portal2", 105 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 106 | } 107 | ], 108 | "pools": [ 109 | { 110 | "pool": "rbd", 111 | "gateways": [ 112 | { 113 | "host": "igw1", 114 | "tpg": [ 115 | { 116 | "portal": "portal1", 117 | "image": "city", 118 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 119 | } 120 | ] 121 | }, 122 | { 123 | "host": "igw2", 124 | "tpg": [ 125 | { 126 | "portal": "portal2", 127 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 128 | "image": "writers" 129 | }, 130 | { 131 | "portal": "portal2", 132 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 133 | "image": "writers" 134 | }, 135 | { 136 | "portal": "portal2", 137 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 138 | "image": "wood" 139 | } 140 | ] 141 | } 142 | ] 143 | }, 144 | { 145 | "pool": "car", 146 | "gateways": [ 147 | { 148 | "host": "igw1", 149 | "tpg": [ 150 | { 151 | "portal": "portal1", 152 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 153 | "image": "cement" 154 | } 155 | ] 156 | } 157 | ] 158 | }, 159 | { 160 | "pool": "whirl", 161 | "gateways": [ 162 | { 163 | "host": "igw2", 164 | "tpg": [ 165 | { 166 | "portal": "portal2", 167 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 168 | "image": "cheese" 169 | } 170 | ] 171 | } 172 | ] 173 | } 174 | ] 175 | } 176 | -------------------------------------------------------------------------------- /samples/acls.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "acls", 16 | "acls": [ 17 | { 18 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 19 | "userid": "initiator1", 20 | "password": "pass1" 21 | } 22 | ] 23 | }, 24 | { 25 | "host": "igw2", 26 | "authentication": "acls", 27 | "acls": [ 28 | { 29 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 30 | "userid": "initiator1", 31 | "password": "pass1" 32 | }, 33 | { 34 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 35 | "userid": "initiator2", 36 | "password": "pass5" 37 | } 38 | ] 39 | } 40 | ], 41 | "portals": [ 42 | { 43 | "name": "portal1", 44 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 45 | }, 46 | { 47 | "name": "portal2", 48 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 49 | } 50 | ], 51 | "pools": [ 52 | { 53 | "pool": "rbd", 54 | "gateways": [ 55 | { 56 | "host": "igw1", 57 | "tpg": [ 58 | { 59 | "portal": "portal1", 60 | "image": "city", 61 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 62 | } 63 | ] 64 | }, 65 | { 66 | "host": "igw2", 67 | "tpg": [ 68 | { 69 | "portal": "portal2", 70 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 71 | "image": "writers" 72 | }, 73 | { 74 | "portal": "portal2", 75 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 76 | "image": "writers" 77 | }, 78 | { 79 | "portal": "portal2", 80 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 81 | "image": "wood" 82 | } 83 | ] 84 | } 85 | ] 86 | }, 87 | { 88 | "pool": "car", 89 | "gateways": [ 90 | { 91 | "host": "igw1", 92 | "tpg": [ 93 | { 94 | "portal": "portal1", 95 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 96 | "image": "cement" 97 | } 98 | ] 99 | } 100 | ] 101 | }, 102 | { 103 | "pool": "whirl", 104 | "gateways": [ 105 | { 106 | "host": "igw2", 107 | "tpg": [ 108 | { 109 | "portal": "portal2", 110 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 111 | "image": "cheese" 112 | } 113 | ] 114 | } 115 | ] 116 | } 117 | ] 118 | } 119 | -------------------------------------------------------------------------------- /samples/complete.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "tpg+identified", 16 | "discovery": { 17 | "auth": "enable", 18 | "userid": "common2", 19 | "password": "pass1", 20 | "mutual": "enable", 21 | "userid_mutual": "target2", 22 | "password_mutual": "pass2" 23 | }, 24 | "tpg": { 25 | "userid": "common2", 26 | "password": "pass1", 27 | "mutual": "enable", 28 | "userid_mutual": "target2", 29 | "password_mutual": "pass2" 30 | }, 31 | "acls": [ 32 | { 33 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 34 | "userid": "initiator1", 35 | "password": "pass1", 36 | "mutual": "enable", 37 | "userid_mutual": "target1", 38 | "password_mutual": "pass2" 39 | } 40 | ] 41 | }, 42 | { 43 | "host": "igw2", 44 | "authentication": "tpg", 45 | "discovery": { 46 | "auth": "enable", 47 | "userid": "common1", 48 | "password": "pass1", 49 | "mutual": "enable", 50 | "userid_mutual": "target1", 51 | "password_mutual": "pass2" 52 | }, 53 | "tpg": { 54 | "userid": "common1", 55 | "password": "pass1", 56 | "mutual": "enable", 57 | "userid_mutual": "target1", 58 | "password_mutual": "pass2" 59 | }, 60 | "acls": [ 61 | { 62 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 63 | "userid": "initiator1", 64 | "password": "pass3", 65 | "mutual": "enable", 66 | "userid_mutual": "target2", 67 | "password_mutual": "pass4" 68 | }, 69 | { 70 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 71 | "userid": "initiator2", 72 | "password": "pass5", 73 | "mutual": "enable", 74 | "userid_mutual": "target2", 75 | "password_mutual": "pass6" 76 | } 77 | ] 78 | } 79 | ], 80 | "portals": [ 81 | { 82 | "name": "portal1", 83 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 84 | }, 85 | { 86 | "name": "portal2", 87 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 88 | } 89 | ], 90 | "pools": [ 91 | { 92 | "pool": "rbd", 93 | "gateways": [ 94 | { 95 | "host": "igw1", 96 | "tpg": [ 97 | { 98 | "portal": "portal1", 99 | "image": "city", 100 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 101 | } 102 | ] 103 | }, 104 | { 105 | "host": "igw2", 106 | "tpg": [ 107 | { 108 | "portal": "portal2", 109 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 110 | "image": "writers" 111 | }, 112 | { 113 | "portal": "portal2", 114 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 115 | "image": "writers" 116 | }, 117 | { 118 | "portal": "portal2", 119 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 120 | "image": "wood" 121 | } 122 | ] 123 | } 124 | ] 125 | }, 126 | { 127 | "pool": "car", 128 | "gateways": [ 129 | { 130 | "host": "igw1", 131 | "tpg": [ 132 | { 133 | "portal": "portal1", 134 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 135 | "image": "cement" 136 | } 137 | ] 138 | } 139 | ] 140 | }, 141 | { 142 | "pool": "whirl", 143 | "gateways": [ 144 | { 145 | "host": "igw2", 146 | "tpg": [ 147 | { 148 | "portal": "portal2", 149 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 150 | "image": "cheese" 151 | } 152 | ] 153 | } 154 | ] 155 | } 156 | ] 157 | } 158 | -------------------------------------------------------------------------------- /samples/identified+settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "identified", 16 | "identified": [ 17 | { 18 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 19 | "attrib_dataout_timeout": "3", 20 | "attrib_dataout_timeout_retries": "5", 21 | "attrib_default_erl": "0", 22 | "attrib_nopin_response_timeout": "30", 23 | "attrib_nopin_timeout": "15", 24 | "attrib_random_datain_pdu_offsets": "0", 25 | "attrib_random_datain_seq_offsets": "0", 26 | "attrib_random_r2t_offsets": "0", 27 | "param_DataPDUInOrder": "1", 28 | "param_DataSequenceInOrder": "1", 29 | "param_DefaultTime2Retain": "0", 30 | "param_DefaultTime2Wait": "2", 31 | "param_ErrorRecoveryLevel": "0", 32 | "param_FirstBurstLength": "65536", 33 | "param_ImmediateData": "1", 34 | "param_InitialR2T": "1", 35 | "param_MaxBurstLength": "262144", 36 | "param_MaxConnections": "1", 37 | "param_MaxOutstandingR2T": "1" 38 | } 39 | ] 40 | }, 41 | { 42 | "host": "igw2", 43 | "authentication": "identified", 44 | "identified": [ 45 | { 46 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 47 | "attrib_dataout_timeout": "3", 48 | "attrib_dataout_timeout_retries": "5", 49 | "attrib_default_erl": "0", 50 | "attrib_nopin_response_timeout": "30", 51 | "attrib_nopin_timeout": "15", 52 | "attrib_random_datain_pdu_offsets": "0", 53 | "attrib_random_datain_seq_offsets": "0", 54 | "attrib_random_r2t_offsets": "0", 55 | "param_DataPDUInOrder": "1", 56 | "param_DataSequenceInOrder": "1", 57 | "param_DefaultTime2Retain": "0", 58 | "param_DefaultTime2Wait": "2", 59 | "param_ErrorRecoveryLevel": "0", 60 | "param_FirstBurstLength": "65536", 61 | "param_ImmediateData": "1", 62 | "param_InitialR2T": "1", 63 | "param_MaxBurstLength": "262144", 64 | "param_MaxConnections": "1", 65 | "param_MaxOutstandingR2T": "1" 66 | } 67 | ] 68 | } 69 | ], 70 | "portals": [ 71 | { 72 | "name": "portal1", 73 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 74 | }, 75 | { 76 | "name": "portal2", 77 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 78 | } 79 | ], 80 | "pools": [ 81 | { 82 | "pool": "rbd", 83 | "gateways": [ 84 | { 85 | "host": "igw1", 86 | "tpg": [ 87 | { 88 | "portal": "portal1", 89 | "image": "city", 90 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 91 | } 92 | ] 93 | }, 94 | { 95 | "host": "igw2", 96 | "tpg": [ 97 | { 98 | "portal": "portal2", 99 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 100 | "image": "writers" 101 | }, 102 | { 103 | "portal": "portal2", 104 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 105 | "image": "writers" 106 | }, 107 | { 108 | "portal": "portal2", 109 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 110 | "image": "wood" 111 | } 112 | ] 113 | } 114 | ] 115 | }, 116 | { 117 | "pool": "car", 118 | "gateways": [ 119 | { 120 | "host": "igw1", 121 | "tpg": [ 122 | { 123 | "portal": "portal1", 124 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 125 | "image": "cement" 126 | } 127 | ] 128 | } 129 | ] 130 | }, 131 | { 132 | "pool": "whirl", 133 | "gateways": [ 134 | { 135 | "host": "igw2", 136 | "tpg": [ 137 | { 138 | "portal": "portal2", 139 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 140 | "image": "cheese" 141 | } 142 | ] 143 | } 144 | ] 145 | } 146 | ] 147 | } 148 | -------------------------------------------------------------------------------- /samples/identified.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "identified", 16 | }, 17 | { 18 | "host": "igw2", 19 | "authentication": "identified", 20 | } 21 | ], 22 | "portals": [ 23 | { 24 | "name": "portal1", 25 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 26 | }, 27 | { 28 | "name": "portal2", 29 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 30 | } 31 | ], 32 | "pools": [ 33 | { 34 | "pool": "rbd", 35 | "gateways": [ 36 | { 37 | "host": "igw1", 38 | "tpg": [ 39 | { 40 | "portal": "portal1", 41 | "image": "city", 42 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 43 | } 44 | ] 45 | }, 46 | { 47 | "host": "igw2", 48 | "tpg": [ 49 | { 50 | "portal": "portal2", 51 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 52 | "image": "writers" 53 | }, 54 | { 55 | "portal": "portal2", 56 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 57 | "image": "writers" 58 | }, 59 | { 60 | "portal": "portal2", 61 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 62 | "image": "wood" 63 | } 64 | ] 65 | } 66 | ] 67 | }, 68 | { 69 | "pool": "car", 70 | "gateways": [ 71 | { 72 | "host": "igw1", 73 | "tpg": [ 74 | { 75 | "portal": "portal1", 76 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 77 | "image": "cement" 78 | } 79 | ] 80 | } 81 | ] 82 | }, 83 | { 84 | "pool": "whirl", 85 | "gateways": [ 86 | { 87 | "host": "igw2", 88 | "tpg": [ 89 | { 90 | "portal": "portal2", 91 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 92 | "image": "cheese" 93 | } 94 | ] 95 | } 96 | ] 97 | } 98 | ] 99 | } 100 | -------------------------------------------------------------------------------- /samples/no_authentication+explicit.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "none" 16 | }, 17 | { 18 | "host": "igw2", 19 | "authentication": "none" 20 | } 21 | ], 22 | "portals": [ 23 | { 24 | "name": "portal1", 25 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 26 | }, 27 | { 28 | "name": "portal2", 29 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 30 | } 31 | ], 32 | "pools": [ 33 | { 34 | "pool": "rbd", 35 | "gateways": [ 36 | { 37 | "host": "igw1", 38 | "tpg": [ 39 | { 40 | "portal": "portal1", 41 | "image": "city", 42 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 43 | } 44 | ] 45 | }, 46 | { 47 | "host": "igw2", 48 | "tpg": [ 49 | { 50 | "portal": "portal2", 51 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 52 | "image": "writers" 53 | }, 54 | { 55 | "portal": "portal2", 56 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 57 | "image": "writers" 58 | }, 59 | { 60 | "portal": "portal2", 61 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 62 | "image": "wood" 63 | } 64 | ] 65 | } 66 | ] 67 | }, 68 | { 69 | "pool": "car", 70 | "gateways": [ 71 | { 72 | "host": "igw1", 73 | "tpg": [ 74 | { 75 | "portal": "portal1", 76 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 77 | "image": "cement" 78 | } 79 | ] 80 | } 81 | ] 82 | } 83 | ] 84 | } 85 | -------------------------------------------------------------------------------- /samples/no_authentication.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "portals": [ 13 | { 14 | "name": "portal1", 15 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 16 | }, 17 | { 18 | "name": "portal2", 19 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 20 | } 21 | ], 22 | "pools": [ 23 | { 24 | "pool": "rbd", 25 | "gateways": [ 26 | { 27 | "host": "igw1", 28 | "tpg": [ 29 | { 30 | "portal": "portal1", 31 | "image": "city", 32 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 33 | } 34 | ] 35 | }, 36 | { 37 | "host": "igw2", 38 | "tpg": [ 39 | { 40 | "portal": "portal2", 41 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 42 | "image": "writers" 43 | }, 44 | { 45 | "portal": "portal2", 46 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 47 | "image": "writers" 48 | }, 49 | { 50 | "portal": "portal2", 51 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 52 | "image": "wood" 53 | } 54 | ] 55 | } 56 | ] 57 | }, 58 | { 59 | "pool": "car", 60 | "gateways": [ 61 | { 62 | "host": "igw1", 63 | "tpg": [ 64 | { 65 | "portal": "portal1", 66 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 67 | "image": "cement" 68 | } 69 | ] 70 | } 71 | ] 72 | } 73 | ] 74 | } 75 | -------------------------------------------------------------------------------- /samples/nonstandard_port+no_authentication.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | } 7 | ], 8 | "auth": [ 9 | { 10 | "host": "igw1", 11 | "authentication": "none" 12 | } 13 | ], 14 | "portals": [ 15 | { 16 | "name": "portal1", 17 | "addresses": [ "172.16.1.16 3261", "172.16.2.16 3261" ] 18 | } 19 | ], 20 | "pools": [ 21 | { 22 | "pool": "rbd", 23 | "gateways": [ 24 | { 25 | "host": "igw1", 26 | "tpg": [ 27 | { 28 | "portal": "portal1", 29 | "image": "city", 30 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 31 | } 32 | ] 33 | } 34 | ] 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /samples/plain+2gateways+2portals+2images+isolated+combined.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": [ 3 | { 4 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant", 5 | "authentication": "acls", 6 | "acls": [ 7 | { 8 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 9 | "userid": "common1", 10 | "password": "pass1" 11 | } 12 | ] 13 | }, 14 | { 15 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant-too", 16 | "authentication": "acls", 17 | "acls": [ 18 | { 19 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 20 | "userid": "common2", 21 | "password": "pass2" 22 | } 23 | ] 24 | }, 25 | { 26 | "host": "igw1", 27 | "authentication": "tpg", 28 | "tpg": { 29 | "userid": "common1", 30 | "password": "pass1" 31 | } 32 | } 33 | ], 34 | "targets": [ 35 | { 36 | "hosts": [ 37 | { "host": "igw1", "portal": "portal1" }, 38 | { "host": "igw2", "portal": "portal2" } 39 | ], 40 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant" 41 | }, 42 | { 43 | "hosts": [ 44 | { "host": "igw1", "portal": "portal3" }, 45 | { "host": "igw2", "portal": "portal4" } 46 | ], 47 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant-too" 48 | }, 49 | { 50 | "host": "igw1", 51 | "target": "iqn.2003-01.org.linux-iscsi:generic.x86:sn.abcdefghijk" 52 | } 53 | ], 54 | "portals": [ 55 | { 56 | "name": "portal1", 57 | "addresses": [ "172.16.1.16" ] 58 | }, 59 | { 60 | "name": "portal2", 61 | "addresses": [ "172.16.1.17" ] 62 | }, 63 | { 64 | "name": "portal3", 65 | "addresses": [ "172.16.2.16" ] 66 | }, 67 | { 68 | "name": "portal4", 69 | "addresses": [ "172.16.2.17" ] 70 | } 71 | ], 72 | "pools": [ 73 | { 74 | "pool": "rbd", 75 | "gateways": [ 76 | { 77 | "host": "igw1", 78 | "tpg": [ 79 | { 80 | "image": "archive", 81 | "portal": "portal1" 82 | } 83 | ] 84 | }, 85 | { 86 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant", 87 | "tpg": [ 88 | { 89 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 90 | "image": "city" 91 | } 92 | ] 93 | }, 94 | { 95 | "target": "iqn.2003-01.org.linux-iscsi:igw.x86:sn.redundant-too", 96 | "tpg": [ 97 | { 98 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 99 | "image": "wood" 100 | } 101 | ] 102 | } 103 | ] 104 | } 105 | ] 106 | } 107 | -------------------------------------------------------------------------------- /samples/plain+attributes.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:generic.x86:sn.abcdefghijk", 6 | "tpg_login_timeout": "10", 7 | "tpg_default_cmdsn_depth": "64", 8 | "tpg_default_erl": "0", 9 | "tpg_login_timeout": "10", 10 | "tpg_netif_timeout": "2", 11 | "tpg_prod_mode_write_protect": "0", 12 | "tpg_t10_pi": "0" 13 | } 14 | ], 15 | "auth": [ 16 | { 17 | "host": "igw1", 18 | "authentication": "tpg", 19 | "tpg": { 20 | "userid": "common1", 21 | "password": "pass1" 22 | } 23 | } 24 | ], 25 | "pools": [ 26 | { 27 | "pool": "rbd", 28 | "gateways": [ 29 | { 30 | "host": "igw1", 31 | "tpg": [ 32 | { 33 | "image": "archive", 34 | "backstore_block_size": "1024" 35 | }, 36 | { 37 | "image": "archive1", 38 | "backstore_block_size": "512", 39 | "backstore_emulate_3pc": "1", 40 | "backstore_emulate_caw": "1", 41 | "backstore_emulate_dpo": "0", 42 | "backstore_emulate_fua_read": "0", 43 | "backstore_emulate_fua_write": "1", 44 | "backstore_emulate_model_alias": "0", 45 | "backstore_emulate_rest_reord": "0", 46 | "backstore_emulate_tas": "1", 47 | "backstore_emulate_tpu": "0", 48 | "backstore_emulate_tpws": "0", 49 | "backstore_emulate_ua_intlck_ctrl": "0", 50 | "backstore_emulate_write_cache": "0", 51 | "backstore_enforce_pr_isids": "1", 52 | "backstore_hw_block_size": "512", 53 | "backstore_hw_max_sectors": "8192", 54 | "backstore_hw_pi_prot_type": "0", 55 | "backstore_hw_queue_depth": "128", 56 | "backstore_is_nonrot": "1", 57 | "backstore_max_unmap_block_desc_count": "1", 58 | "backstore_max_unmap_lba_count": "8192", 59 | "backstore_max_write_same_len": "65535", 60 | "backstore_optimal_sectors": "8192", 61 | "backstore_pi_prot_format": "0", 62 | "backstore_pi_prot_type": "0", 63 | "backstore_queue_depth": "128", 64 | "backstore_unmap_granularity": "8192", 65 | "backstore_unmap_granularity_alignment": "4194304" 66 | } 67 | ] 68 | } 69 | ] 70 | } 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /samples/plain+rbd_name.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:generic.x86:sn.abcdefghijk" 6 | } 7 | ], 8 | "auth": [ 9 | { 10 | "host": "igw1", 11 | "authentication": "tpg", 12 | "tpg": { 13 | "userid": "common1", 14 | "password": "pass1" 15 | } 16 | } 17 | ], 18 | "pools": [ 19 | { 20 | "pool": "rbd", 21 | "gateways": [ 22 | { 23 | "host": "igw1", 24 | "tpg": [ 25 | { 26 | "image": "archive", 27 | "rbd_name": "simple" 28 | } 29 | ] 30 | } 31 | ] 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /samples/plain+retries.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:generic.x86:sn.abcdefghijk" 6 | } 7 | ], 8 | "auth": [ 9 | { 10 | "host": "igw1", 11 | "authentication": "tpg", 12 | "tpg": { 13 | "userid": "common1", 14 | "password": "pass1" 15 | } 16 | } 17 | ], 18 | "pools": [ 19 | { 20 | "pool": "rbd", 21 | "gateways": [ 22 | { 23 | "host": "igw1", 24 | "tpg": [ 25 | { 26 | "image": "archive", 27 | "retries": "3", 28 | "sleep": "4", 29 | "retry_errors": [ 95 ] 30 | } 31 | ] 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /samples/plain+uuid.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:generic.x86:sn.abcdefghijk" 6 | } 7 | ], 8 | "auth": [ 9 | { 10 | "host": "igw1", 11 | "authentication": "tpg", 12 | "tpg": { 13 | "userid": "common1", 14 | "password": "pass1" 15 | } 16 | } 17 | ], 18 | "pools": [ 19 | { 20 | "pool": "rbd", 21 | "gateways": [ 22 | { 23 | "host": "igw1", 24 | "tpg": [ 25 | { 26 | "image": "archive", 27 | "uuid": "12345678-abcd-9012-efab-345678901234" 28 | } 29 | ] 30 | } 31 | ] 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /samples/plain+wwn_generate.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:generic.x86:sn.abcdefghijk", 6 | "wwn_generate": "original" 7 | } 8 | ], 9 | "auth": [ 10 | { 11 | "host": "igw1", 12 | "authentication": "tpg", 13 | "tpg": { 14 | "userid": "common1", 15 | "password": "pass1" 16 | } 17 | } 18 | ], 19 | "pools": [ 20 | { 21 | "pool": "rbd", 22 | "gateways": [ 23 | { 24 | "host": "igw1", 25 | "tpg": [ 26 | { 27 | "image": "archive" 28 | } 29 | ] 30 | } 31 | ] 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /samples/plain.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:generic.x86:sn.abcdefghijk" 6 | } 7 | ], 8 | "auth": [ 9 | { 10 | "host": "igw1", 11 | "authentication": "tpg", 12 | "tpg": { 13 | "userid": "common1", 14 | "password": "pass1" 15 | } 16 | } 17 | ], 18 | "pools": [ 19 | { 20 | "pool": "rbd", 21 | "gateways": [ 22 | { 23 | "host": "igw1", 24 | "tpg": [ 25 | { 26 | "image": "archive" 27 | } 28 | ] 29 | } 30 | ] 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /samples/simple.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:generic.x86:sn.abcdefghijk" 6 | } 7 | ], 8 | "auth": [ 9 | { 10 | "host": "igw1", 11 | "authentication": "tpg", 12 | "tpg": { 13 | "userid": "common1", 14 | "password": "pass1" 15 | } 16 | } 17 | ], 18 | "portals": [ 19 | { 20 | "name": "portal1", 21 | "addresses": [ "172.16.1.16" ] 22 | } 23 | ], 24 | "pools": [ 25 | { 26 | "pool": "rbd", 27 | "gateways": [ 28 | { 29 | "host": "igw1", 30 | "tpg": [ 31 | { 32 | "portal": "portal1", 33 | "image": "archive" 34 | } 35 | ] 36 | } 37 | ] 38 | } 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /samples/tpg+discovery+mutual.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "tpg", 16 | "discovery": { 17 | "auth": "enable", 18 | "userid": "common2", 19 | "password": "pass1", 20 | "mutual": "enable", 21 | "userid_mutual": "target2", 22 | "password_mutual": "pass2" 23 | }, 24 | "tpg": { 25 | "userid": "common2", 26 | "password": "pass1" 27 | } 28 | }, 29 | { 30 | "host": "igw2", 31 | "authentication": "tpg", 32 | "discovery": { 33 | "auth": "enable", 34 | "userid": "common1", 35 | "password": "pass1", 36 | "mutual": "enable", 37 | "userid_mutual": "target1", 38 | "password_mutual": "pass2" 39 | }, 40 | "tpg": { 41 | "userid": "common1", 42 | "password": "pass1" 43 | } 44 | } 45 | ], 46 | "portals": [ 47 | { 48 | "name": "portal1", 49 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 50 | }, 51 | { 52 | "name": "portal2", 53 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 54 | } 55 | ], 56 | "pools": [ 57 | { 58 | "pool": "rbd", 59 | "gateways": [ 60 | { 61 | "host": "igw1", 62 | "tpg": [ 63 | { 64 | "portal": "portal1", 65 | "image": "city" 66 | } 67 | ] 68 | }, 69 | { 70 | "host": "igw2", 71 | "tpg": [ 72 | { 73 | "portal": "portal2", 74 | "image": "writers" 75 | }, 76 | { 77 | "portal": "portal2", 78 | "image": "writers" 79 | }, 80 | { 81 | "portal": "portal2", 82 | "image": "wood" 83 | } 84 | ] 85 | } 86 | ] 87 | }, 88 | { 89 | "pool": "car", 90 | "gateways": [ 91 | { 92 | "host": "igw1", 93 | "tpg": [ 94 | { 95 | "portal": "portal1", 96 | "image": "cement" 97 | } 98 | ] 99 | } 100 | ] 101 | }, 102 | { 103 | "pool": "whirl", 104 | "gateways": [ 105 | { 106 | "host": "igw2", 107 | "tpg": [ 108 | { 109 | "portal": "portal2", 110 | "image": "cheese" 111 | } 112 | ] 113 | } 114 | ] 115 | } 116 | ] 117 | } 118 | -------------------------------------------------------------------------------- /samples/tpg+discovery.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "tpg", 16 | "discovery": { 17 | "auth": "enable", 18 | "userid": "common2", 19 | "password": "pass1" 20 | }, 21 | "tpg": { 22 | "userid": "common2", 23 | "password": "pass1" 24 | } 25 | }, 26 | { 27 | "host": "igw2", 28 | "authentication": "tpg", 29 | "discovery": { 30 | "auth": "enable", 31 | "userid": "common1", 32 | "password": "pass1" 33 | }, 34 | "tpg": { 35 | "userid": "common1", 36 | "password": "pass1" 37 | } 38 | } 39 | ], 40 | "portals": [ 41 | { 42 | "name": "portal1", 43 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 44 | }, 45 | { 46 | "name": "portal2", 47 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 48 | } 49 | ], 50 | "pools": [ 51 | { 52 | "pool": "rbd", 53 | "gateways": [ 54 | { 55 | "host": "igw1", 56 | "tpg": [ 57 | { 58 | "portal": "portal1", 59 | "image": "city" 60 | } 61 | ] 62 | }, 63 | { 64 | "host": "igw2", 65 | "tpg": [ 66 | { 67 | "portal": "portal2", 68 | "image": "writers" 69 | }, 70 | { 71 | "portal": "portal2", 72 | "image": "writers" 73 | }, 74 | { 75 | "portal": "portal2", 76 | "image": "wood" 77 | } 78 | ] 79 | } 80 | ] 81 | }, 82 | { 83 | "pool": "car", 84 | "gateways": [ 85 | { 86 | "host": "igw1", 87 | "tpg": [ 88 | { 89 | "portal": "portal1", 90 | "image": "cement" 91 | } 92 | ] 93 | } 94 | ] 95 | }, 96 | { 97 | "pool": "whirl", 98 | "gateways": [ 99 | { 100 | "host": "igw2", 101 | "tpg": [ 102 | { 103 | "portal": "portal2", 104 | "image": "cheese" 105 | } 106 | ] 107 | } 108 | ] 109 | } 110 | ] 111 | } 112 | -------------------------------------------------------------------------------- /samples/tpg+identified+mutual+discovery+mutual.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "tpg", 16 | "discovery": { 17 | "auth": "enable", 18 | "userid": "common2", 19 | "password": "pass1", 20 | "mutual": "enable", 21 | "userid_mutual": "target2", 22 | "password_mutual": "pass2" 23 | }, 24 | "tpg": { 25 | "userid": "common2", 26 | "password": "pass1", 27 | "mutual": "enable", 28 | "userid_mutual": "target2", 29 | "password_mutual": "pass2" 30 | } 31 | }, 32 | { 33 | "host": "igw2", 34 | "authentication": "tpg", 35 | "discovery": { 36 | "auth": "enable", 37 | "userid": "common1", 38 | "password": "pass1", 39 | "mutual": "enable", 40 | "userid_mutual": "target1", 41 | "password_mutual": "pass2" 42 | }, 43 | "tpg": { 44 | "userid": "common1", 45 | "password": "pass1", 46 | "mutual": "enable", 47 | "userid_mutual": "target1", 48 | "password_mutual": "pass2" 49 | } 50 | } 51 | ], 52 | "portals": [ 53 | { 54 | "name": "portal1", 55 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 56 | }, 57 | { 58 | "name": "portal2", 59 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 60 | } 61 | ], 62 | "pools": [ 63 | { 64 | "pool": "rbd", 65 | "gateways": [ 66 | { 67 | "host": "igw1", 68 | "tpg": [ 69 | { 70 | "portal": "portal1", 71 | "image": "city", 72 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 73 | } 74 | ] 75 | }, 76 | { 77 | "host": "igw2", 78 | "tpg": [ 79 | { 80 | "portal": "portal2", 81 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 82 | "image": "writers" 83 | }, 84 | { 85 | "portal": "portal2", 86 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 87 | "image": "writers" 88 | }, 89 | { 90 | "portal": "portal2", 91 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 92 | "image": "wood" 93 | } 94 | ] 95 | } 96 | ] 97 | }, 98 | { 99 | "pool": "car", 100 | "gateways": [ 101 | { 102 | "host": "igw1", 103 | "tpg": [ 104 | { 105 | "portal": "portal1", 106 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 107 | "image": "cement" 108 | } 109 | ] 110 | } 111 | ] 112 | }, 113 | { 114 | "pool": "whirl", 115 | "gateways": [ 116 | { 117 | "host": "igw2", 118 | "tpg": [ 119 | { 120 | "portal": "portal2", 121 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 122 | "image": "cheese" 123 | } 124 | ] 125 | } 126 | ] 127 | } 128 | ] 129 | } 130 | -------------------------------------------------------------------------------- /samples/tpg+identified.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "tpg+identified", 16 | "tpg": { 17 | "userid": "common2", 18 | "password": "pass1" 19 | } 20 | }, 21 | { 22 | "host": "igw2", 23 | "authentication": "tpg+identified", 24 | "tpg": { 25 | "userid": "common1", 26 | "password": "pass1" 27 | } 28 | } 29 | ], 30 | "portals": [ 31 | { 32 | "name": "portal1", 33 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 34 | }, 35 | { 36 | "name": "portal2", 37 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 38 | } 39 | ], 40 | "pools": [ 41 | { 42 | "pool": "rbd", 43 | "gateways": [ 44 | { 45 | "host": "igw1", 46 | "tpg": [ 47 | { 48 | "portal": "portal1", 49 | "image": "city", 50 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20" 51 | } 52 | ] 53 | }, 54 | { 55 | "host": "igw2", 56 | "tpg": [ 57 | { 58 | "portal": "portal2", 59 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 60 | "image": "writers" 61 | }, 62 | { 63 | "portal": "portal2", 64 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 65 | "image": "writers" 66 | }, 67 | { 68 | "portal": "portal2", 69 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f24", 70 | "image": "wood" 71 | } 72 | ] 73 | } 74 | ] 75 | }, 76 | { 77 | "pool": "car", 78 | "gateways": [ 79 | { 80 | "host": "igw1", 81 | "tpg": [ 82 | { 83 | "portal": "portal1", 84 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 85 | "image": "cement" 86 | } 87 | ] 88 | } 89 | ] 90 | }, 91 | { 92 | "pool": "whirl", 93 | "gateways": [ 94 | { 95 | "host": "igw2", 96 | "tpg": [ 97 | { 98 | "portal": "portal2", 99 | "initiator": "iqn.1996-04.de.suse:01:e6ca28cc9f20", 100 | "image": "cheese" 101 | } 102 | ] 103 | } 104 | ] 105 | } 106 | ] 107 | } 108 | -------------------------------------------------------------------------------- /samples/tpg+mutual+discovery+mutual.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "tpg", 16 | "discovery": { 17 | "auth": "enable", 18 | "userid": "common2", 19 | "password": "pass1", 20 | "mutual": "enable", 21 | "userid_mutual": "target2", 22 | "password_mutual": "pass2" 23 | }, 24 | "tpg": { 25 | "userid": "common2", 26 | "password": "pass1", 27 | "mutual": "enable", 28 | "userid_mutual": "target2", 29 | "password_mutual": "pass2" 30 | } 31 | }, 32 | { 33 | "host": "igw2", 34 | "authentication": "tpg", 35 | "discovery": { 36 | "auth": "enable", 37 | "userid": "common1", 38 | "password": "pass1", 39 | "mutual": "enable", 40 | "userid_mutual": "target1", 41 | "password_mutual": "pass2" 42 | }, 43 | "tpg": { 44 | "userid": "common1", 45 | "password": "pass1", 46 | "mutual": "enable", 47 | "userid_mutual": "target1", 48 | "password_mutual": "pass2" 49 | } 50 | } 51 | ], 52 | "portals": [ 53 | { 54 | "name": "portal1", 55 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 56 | }, 57 | { 58 | "name": "portal2", 59 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 60 | } 61 | ], 62 | "pools": [ 63 | { 64 | "pool": "rbd", 65 | "gateways": [ 66 | { 67 | "host": "igw1", 68 | "tpg": [ 69 | { 70 | "portal": "portal1", 71 | "image": "city" 72 | } 73 | ] 74 | }, 75 | { 76 | "host": "igw2", 77 | "tpg": [ 78 | { 79 | "portal": "portal2", 80 | "image": "writers" 81 | }, 82 | { 83 | "portal": "portal2", 84 | "image": "writers" 85 | }, 86 | { 87 | "portal": "portal2", 88 | "image": "wood" 89 | } 90 | ] 91 | } 92 | ] 93 | }, 94 | { 95 | "pool": "car", 96 | "gateways": [ 97 | { 98 | "host": "igw1", 99 | "tpg": [ 100 | { 101 | "portal": "portal1", 102 | "image": "cement" 103 | } 104 | ] 105 | } 106 | ] 107 | }, 108 | { 109 | "pool": "whirl", 110 | "gateways": [ 111 | { 112 | "host": "igw2", 113 | "tpg": [ 114 | { 115 | "portal": "portal2", 116 | "image": "cheese" 117 | } 118 | ] 119 | } 120 | ] 121 | } 122 | ] 123 | } 124 | -------------------------------------------------------------------------------- /samples/tpg+mutual+discovery.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "tpg", 16 | "discovery": { 17 | "auth": "enable", 18 | "userid": "common2", 19 | "password": "pass1" 20 | }, 21 | "tpg": { 22 | "userid": "common2", 23 | "password": "pass1", 24 | "mutual": "enable", 25 | "userid_mutual": "target2", 26 | "password_mutual": "pass2" 27 | } 28 | }, 29 | { 30 | "host": "igw2", 31 | "authentication": "tpg", 32 | "discovery": { 33 | "auth": "enable", 34 | "userid": "common1", 35 | "password": "pass1" 36 | }, 37 | "tpg": { 38 | "userid": "common1", 39 | "password": "pass1", 40 | "mutual": "enable", 41 | "userid_mutual": "target1", 42 | "password_mutual": "pass2" 43 | } 44 | } 45 | ], 46 | "portals": [ 47 | { 48 | "name": "portal1", 49 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 50 | }, 51 | { 52 | "name": "portal2", 53 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 54 | } 55 | ], 56 | "pools": [ 57 | { 58 | "pool": "rbd", 59 | "gateways": [ 60 | { 61 | "host": "igw1", 62 | "tpg": [ 63 | { 64 | "portal": "portal1", 65 | "image": "city" 66 | } 67 | ] 68 | }, 69 | { 70 | "host": "igw2", 71 | "tpg": [ 72 | { 73 | "portal": "portal2", 74 | "image": "writers" 75 | }, 76 | { 77 | "portal": "portal2", 78 | "image": "writers" 79 | }, 80 | { 81 | "portal": "portal2", 82 | "image": "wood" 83 | } 84 | ] 85 | } 86 | ] 87 | }, 88 | { 89 | "pool": "car", 90 | "gateways": [ 91 | { 92 | "host": "igw1", 93 | "tpg": [ 94 | { 95 | "portal": "portal1", 96 | "image": "cement" 97 | } 98 | ] 99 | } 100 | ] 101 | }, 102 | { 103 | "pool": "whirl", 104 | "gateways": [ 105 | { 106 | "host": "igw2", 107 | "tpg": [ 108 | { 109 | "portal": "portal2", 110 | "image": "cheese" 111 | } 112 | ] 113 | } 114 | ] 115 | } 116 | ] 117 | } 118 | -------------------------------------------------------------------------------- /samples/tpg+mutual.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "auth": [ 13 | { 14 | "authentication": "tpg", 15 | "host": "igw1", 16 | "tpg": { 17 | "mutual": "enable", 18 | "password": "pass1", 19 | "password_mutual": "pass2", 20 | "userid": "common2", 21 | "userid_mutual": "target2" 22 | } 23 | }, 24 | { 25 | "authentication": "tpg", 26 | "host": "igw2", 27 | "tpg": { 28 | "mutual": "enable", 29 | "password": "pass1", 30 | "password_mutual": "pass2", 31 | "userid": "common1", 32 | "userid_mutual": "target1" 33 | } 34 | } 35 | ], 36 | "portals": [ 37 | { 38 | "name": "portal1", 39 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 40 | }, 41 | { 42 | "name": "portal2", 43 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 44 | } 45 | ], 46 | "pools": [ 47 | { 48 | "pool": "rbd", 49 | "gateways": [ 50 | { 51 | "host": "igw1", 52 | "tpg": [ 53 | { 54 | "portal": "portal1", 55 | "image": "city" 56 | } 57 | ] 58 | }, 59 | { 60 | "host": "igw2", 61 | "tpg": [ 62 | { 63 | "portal": "portal2", 64 | "image": "writers" 65 | }, 66 | { 67 | "portal": "portal2", 68 | "image": "writers" 69 | }, 70 | { 71 | "portal": "portal2", 72 | "image": "wood" 73 | } 74 | ] 75 | } 76 | ] 77 | }, 78 | { 79 | "pool": "car", 80 | "gateways": [ 81 | { 82 | "host": "igw1", 83 | "tpg": [ 84 | { 85 | "portal": "portal1", 86 | "image": "cement" 87 | } 88 | ] 89 | } 90 | ] 91 | }, 92 | { 93 | "pool": "whirl", 94 | "gateways": [ 95 | { 96 | "host": "igw2", 97 | "tpg": [ 98 | { 99 | "portal": "portal2", 100 | "image": "cheese" 101 | } 102 | ] 103 | } 104 | ] 105 | } 106 | ] 107 | } 108 | -------------------------------------------------------------------------------- /samples/tpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "host": "igw1", 5 | "target": "iqn.2003-01.org.linux-iscsi:igw1.x86:sn.1a2b6ae09141" 6 | }, 7 | { 8 | "host": "igw2", 9 | "target": "iqn.2003-01.org.linux-iscsi:igw2.x86:sn.b611a553e579" 10 | } 11 | ], 12 | "auth": [ 13 | { 14 | "host": "igw1", 15 | "authentication": "tpg", 16 | "tpg": { 17 | "userid": "common2", 18 | "password": "pass1" 19 | } 20 | }, 21 | { 22 | "host": "igw2", 23 | "authentication": "tpg", 24 | "tpg": { 25 | "userid": "common1", 26 | "password": "pass1" 27 | } 28 | } 29 | ], 30 | "portals": [ 31 | { 32 | "name": "portal1", 33 | "addresses": [ "172.16.1.16", "172.16.2.16" ] 34 | }, 35 | { 36 | "name": "portal2", 37 | "addresses": [ "172.16.1.17", "172.16.2.17" ] 38 | } 39 | ], 40 | "pools": [ 41 | { 42 | "pool": "rbd", 43 | "gateways": [ 44 | { 45 | "host": "igw1", 46 | "tpg": [ 47 | { 48 | "portal": "portal1", 49 | "image": "city" 50 | } 51 | ] 52 | }, 53 | { 54 | "host": "igw2", 55 | "tpg": [ 56 | { 57 | "portal": "portal2", 58 | "image": "writers" 59 | }, 60 | { 61 | "portal": "portal2", 62 | "image": "writers" 63 | }, 64 | { 65 | "portal": "portal2", 66 | "image": "wood" 67 | } 68 | ] 69 | } 70 | ] 71 | }, 72 | { 73 | "pool": "car", 74 | "gateways": [ 75 | { 76 | "host": "igw1", 77 | "tpg": [ 78 | { 79 | "portal": "portal1", 80 | "image": "cement" 81 | } 82 | ] 83 | } 84 | ] 85 | }, 86 | { 87 | "pool": "whirl", 88 | "gateways": [ 89 | { 90 | "host": "igw2", 91 | "tpg": [ 92 | { 93 | "portal": "portal2", 94 | "image": "cheese" 95 | } 96 | ] 97 | } 98 | ] 99 | } 100 | ] 101 | } 102 | -------------------------------------------------------------------------------- /sysconfig/lrbd: -------------------------------------------------------------------------------- 1 | ## Path: Applications/System 2 | ## Description: Ceph iSCSI configuration 3 | ## ServiceReload: lrbd 4 | ## Type: string 5 | ## Default: 6 | # 7 | # Command line options for lrbd(8) init script. 8 | # 9 | LRBD_OPTIONS="" 10 | 11 | -------------------------------------------------------------------------------- /systemd/lrbd.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=configures target.service from Ceph 3 | After=network.target 4 | 5 | [Service] 6 | Type=oneshot 7 | RemainAfterExit=yes 8 | EnvironmentFile=-/etc/sysconfig/lrbd 9 | ExecStart=/usr/sbin/lrbd $LRBD_OPTIONS 10 | ExecStop=/usr/sbin/lrbd -Cu 11 | ExecReload=/usr/sbin/lrbd 12 | 13 | [Install] 14 | WantedBy=multi-user.target 15 | -------------------------------------------------------------------------------- /test/test_acls.py: -------------------------------------------------------------------------------- 1 | 2 | from lrbd import Acls, Common, Runtime, entries 3 | from nose.tools import * 4 | import unittest, mock 5 | import re, tempfile 6 | 7 | class AclsTestCase(unittest.TestCase): 8 | 9 | def setUp(self): 10 | Common.config['iqns'] = [ "iqn.xyz" ] 11 | Common.config['auth'] = [ { "host": "igw1", "authentication": "acls" } ] 12 | Common.config['portals'] = [ { "name": "portal1", 13 | "addresses": [ 14 | "172.16.1.16" 15 | ] } ] 16 | Common.config['pools'] = [ 17 | { "pool": "rbd", 18 | "gateways": [ 19 | { "host": "igw1", "tpg": [ 20 | { "image": "archive", 21 | "initiator": "iqn.abc", 22 | "portal": "portal1" } 23 | ] 24 | } ] 25 | } ] 26 | 27 | Runtime.config['addresses'] = [ "172.16.1.16" ] 28 | Runtime.config['portals'] = {} 29 | Runtime.config['portals']["iqn.xyz"] = {} 30 | Runtime.config['portals']["iqn.xyz"]["archive"] = {} 31 | Runtime.config['portals']["iqn.xyz"]["archive"]["portal1"] = "1" 32 | 33 | def test_acls(self): 34 | class mock_Acls(Acls): 35 | 36 | def _find(self): 37 | pass 38 | 39 | def _cmd(self, target, tpg, initiator): 40 | self.called = " ".join([ target, str(tpg), initiator ]) 41 | 42 | self.a = mock_Acls() 43 | assert self.a.called == "iqn.xyz 1 iqn.abc" 44 | 45 | @raises(AttributeError) 46 | def test_tpg(self): 47 | Common.config['auth'] = [ { "host": "igw1", "authentication": "tpg" } ] 48 | class mock_Acls(Acls): 49 | 50 | def _find(self): 51 | pass 52 | 53 | def _cmd(self, target, tpg, initiator): 54 | self.called = True 55 | 56 | self.a = mock_Acls() 57 | self.a.called 58 | 59 | @mock.patch('glob.glob') 60 | def test_find(self, mock_subproc_glob): 61 | mock_subproc_glob.return_value = [ "/s/k/c/t/i/t/t_1/a/iqn.abc" ] 62 | 63 | class mock_Acls(Acls): 64 | 65 | def _cmd(self, target, tpg, initiator): 66 | self.called = " ".join([ target, str(tpg), initiator ]) 67 | 68 | self.a = mock_Acls() 69 | assert self.a.exists == {'iqn.xyz': {'1': ['iqn.abc']}} 70 | 71 | @mock.patch('glob.glob') 72 | def test_find_does_nothing(self, mock_subproc_glob): 73 | 74 | mock_subproc_glob.return_value = [ ] 75 | 76 | class mock_Acls(Acls): 77 | 78 | def _cmd(self, target, tpg, initiator): 79 | self.called = " ".join([ target, str(tpg), initiator ]) 80 | 81 | self.a = mock_Acls() 82 | assert not self.a.initiators 83 | 84 | def test_cmd(self): 85 | 86 | class mock_Acls(Acls): 87 | 88 | def _find(self): 89 | pass 90 | 91 | self.a = mock_Acls() 92 | print self.a.cmds 93 | assert self.a.cmds == [['targetcli', '/iscsi/iqn.xyz/tpg1/acls', 'create', 'iqn.abc']] 94 | 95 | @mock.patch('lrbd.Popen') 96 | def test_create(self, mock_subproc_popen): 97 | 98 | mock_subproc_popen.return_value.returncode = 0 99 | 100 | Common.config['iqns'] = [ "iqn.xyz" ] 101 | Common.config['portals'] = [ { "name": "portal1", 102 | "addresses": [ 103 | "172.16.1.16" 104 | ] } ] 105 | Common.config['pools'] = [ 106 | { "pool": "rbd", 107 | "gateways": [ 108 | { "host": "igw1", "tpg": [ 109 | { "image": "archive", 110 | "initiator": "iqn.abc", 111 | "portal": "portal1" } 112 | ] 113 | } ] 114 | } ] 115 | 116 | Runtime.config['addresses'] = [ "172.16.1.16" ] 117 | Runtime.config['portals'] = {} 118 | Runtime.config['portals']["iqn.xyz"] = {} 119 | Runtime.config['portals']["iqn.xyz"]["archive"] = {} 120 | Runtime.config['portals']["iqn.xyz"]["archive"]["portal1"] = "1" 121 | 122 | 123 | class mock_Acls(Acls): 124 | 125 | def _find(self): 126 | pass 127 | 128 | def _cmd(self, target, tpg, initiator): 129 | self.called = " ".join([ target, str(tpg), initiator ]) 130 | 131 | self.a = mock_Acls() 132 | self.a.cmds = [[ "targetcli", "hello" ]] 133 | self.a.create() 134 | assert mock_subproc_popen.called 135 | -------------------------------------------------------------------------------- /test/test_authentications.py: -------------------------------------------------------------------------------- 1 | 2 | from lrbd import Authentications, Common 3 | import unittest 4 | #import re, tempfile 5 | 6 | class AuthenticationsTestCase(unittest.TestCase): 7 | 8 | def setUp(self): 9 | self.a = Authentications() 10 | self.data = { "host": "igw1", "authentication": "tpg", 11 | "tpg": { "userid": "common1", "password": "pass1" } } 12 | self.a.add(self.data) 13 | 14 | def test_add(self): 15 | self.a.display() 16 | assert self.a.authentications[0]['authentication'] == "tpg" 17 | 18 | def test_purge(self): 19 | Common.hostname = "igw2" 20 | self.a.purge() 21 | self.a.display() 22 | assert not self.a.authentications 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /test/test_backstores.py: -------------------------------------------------------------------------------- 1 | 2 | from lrbd import entries, Backstores, Common, Runtime 3 | import os 4 | import shutil 5 | import tempfile 6 | import unittest 7 | import mock 8 | 9 | class BackstoresTestCase(unittest.TestCase): 10 | 11 | def test_backstores_default(self): 12 | class mock_Backstores(Backstores): 13 | 14 | def _load_modules(self): 15 | pass 16 | 17 | def _rbd(self): 18 | pass 19 | 20 | def _iblock(self): 21 | pass 22 | 23 | self.b = mock_Backstores(None) 24 | assert Runtime.config['backstore'] == "rbd" 25 | 26 | def test_backstores_iblock(self): 27 | class mock_Backstores(Backstores): 28 | 29 | def _load_modules(self): 30 | pass 31 | 32 | def _rbd(self): 33 | pass 34 | 35 | def _iblock(self): 36 | pass 37 | 38 | self.b = mock_Backstores("iblock") 39 | assert Runtime.config['backstore'] == "iblock" 40 | 41 | def test_backstores_rbd(self): 42 | class mock_Backstores(Backstores): 43 | 44 | def _load_modules(self): 45 | pass 46 | 47 | def _rbd(self): 48 | pass 49 | 50 | def _iblock(self): 51 | pass 52 | 53 | self.b = mock_Backstores("rbd") 54 | assert Runtime.config['backstore'] == "rbd" 55 | 56 | 57 | def test_iblock(self): 58 | 59 | Common.config = { 60 | "pools": [ 61 | { "pool": "rbd", 62 | "gateways": [ 63 | { "host": "igw1", "tpg": [ 64 | { "image": "archive" } 65 | ] 66 | } ] 67 | } ] } 68 | 69 | self.b = Backstores("iblock") 70 | assert self.b.cmds == [['targetcli', '/backstores/iblock', 'create', 'name=rbd-archive', 'dev=/dev/rbd/rbd/archive']] 71 | 72 | def test_iblock_simple(self): 73 | 74 | Common.config = { 75 | "pools": [ 76 | { "pool": "rbd", 77 | "gateways": [ 78 | { "host": "igw1", "tpg": [ 79 | { "image": "archive", "rbd_name": "simple" } 80 | ] 81 | } ] 82 | } ] } 83 | 84 | self.b = Backstores("iblock") 85 | print self.b.cmds 86 | assert self.b.cmds == [['targetcli', '/backstores/iblock', 'create', 'name=archive', 'dev=/dev/rbd/rbd/archive']] 87 | 88 | @mock.patch('glob.glob') 89 | def test_iblock_does_nothing(self, mock_subproc_glob): 90 | Common.config = { 91 | "pools": [ 92 | { "pool": "rbd", 93 | "gateways": [ 94 | { "host": "igw1", "tpg": [ 95 | { "image": "archive" } 96 | ] 97 | } ] 98 | } ] } 99 | 100 | mock_subproc_glob.return_value = "globbed/path/name" 101 | self.b = Backstores("iblock") 102 | assert not self.b.cmds 103 | 104 | @mock.patch('glob.glob') 105 | def test_detect_default(self, mock_subproc_glob): 106 | Common.config = { 107 | "pools": [ 108 | { "pool": "rbd", 109 | "gateways": [ 110 | { "host": "igw1", "tpg": [ 111 | { "image": "archive" } 112 | ] 113 | } ] 114 | } ] } 115 | class mock_Backstores(Backstores): 116 | def _load_modules(self): 117 | pass 118 | 119 | mock_subproc_glob.return_value = [] 120 | self.b = mock_Backstores(None) 121 | 122 | assert self.b.selected == "rbd" 123 | 124 | @mock.patch('glob.glob') 125 | def test_detect_existing(self, mock_subproc_glob): 126 | Common.config = { 127 | "pools": [ 128 | { "pool": "rbd", 129 | "gateways": [ 130 | { "host": "igw1", "tpg": [ 131 | { "image": "archive" } 132 | ] 133 | } ] 134 | } ] } 135 | 136 | mock_subproc_glob.return_value = [ "/s/k/c/t/c/BACKSTORE_0/archive" ] 137 | self.b = Backstores(None) 138 | assert self.b.selected == "BACKSTORE" 139 | 140 | def test_rbd(self): 141 | 142 | Common.config = { 143 | "pools": [ 144 | { "pool": "rbd", 145 | "gateways": [ 146 | { "host": "igw1", "tpg": [ 147 | { "image": "archive" } 148 | ] 149 | } ] 150 | } ] } 151 | class mock_Backstores(Backstores): 152 | def _load_modules(self): 153 | pass 154 | 155 | self.b = mock_Backstores("rbd") 156 | assert self.b.cmds == [['targetcli', '/backstores/rbd', 'create', 'name=rbd-archive', 'dev=/dev/rbd/rbd/archive']] 157 | 158 | def test_rbd_simple(self): 159 | 160 | Common.config = { 161 | "pools": [ 162 | { "pool": "rbd", 163 | "gateways": [ 164 | { "host": "igw1", "tpg": [ 165 | { "image": "archive", "rbd_name": "simple" } 166 | ] 167 | } ] 168 | } ] } 169 | class mock_Backstores(Backstores): 170 | def _load_modules(self): 171 | pass 172 | 173 | self.b = mock_Backstores("rbd") 174 | assert self.b.cmds == [['targetcli', '/backstores/rbd', 'create', 'name=archive', 'dev=/dev/rbd/rbd/archive']] 175 | 176 | @mock.patch('glob.glob') 177 | def test_rbd_does_nothing(self, mock_subproc_glob): 178 | Common.config = { 179 | "pools": [ 180 | { "pool": "rbd", 181 | "gateways": [ 182 | { "host": "igw1", "tpg": [ 183 | { "image": "archive" } 184 | ] 185 | } ] 186 | } ] } 187 | class mock_Backstores(Backstores): 188 | def _load_modules(self): 189 | pass 190 | 191 | mock_subproc_glob.return_value = "globbed/path/name" 192 | self.b = mock_Backstores("rbd") 193 | assert not self.b.cmds 194 | 195 | 196 | @mock.patch('lrbd.Popen') 197 | def test_create(self, mock_subproc_popen): 198 | mock_subproc_popen.return_value.returncode = 0 199 | Common.config = { 200 | "pools": [ 201 | { "pool": "rbd", 202 | "gateways": [ 203 | { "host": "igw1", "tpg": [ 204 | { "image": "archive" } 205 | ] 206 | } ] 207 | } ] } 208 | 209 | self.b = Backstores("iblock") 210 | self.b.cmds = [[ "targetcli", "hello" ]] 211 | self.b.create() 212 | assert mock_subproc_popen.called 213 | 214 | -------------------------------------------------------------------------------- /test/test_content.py: -------------------------------------------------------------------------------- 1 | 2 | from lrbd import Content, InitialContents, Common 3 | from nose.tools import * 4 | import unittest, mock 5 | import re, tempfile 6 | 7 | class InitialContentsTestCase(unittest.TestCase): 8 | 9 | def setUp(self): 10 | Common.config = { "auth": [], "targets": [], "pools": [] } 11 | self.initialcontents = InitialContents() 12 | 13 | def test_instructions(self): 14 | assert re.match(r'#.*\n', self.initialcontents._instructions()) 15 | 16 | 17 | class ContentTestCase(unittest.TestCase): 18 | 19 | def setUp(self): 20 | self.content = Content() 21 | 22 | def test_read(self): 23 | data = '''{ "pools": [ { "pool": "rbd", 24 | "gateways": [ { 25 | "host": "igw1", 26 | "tpg": [ { 27 | "image": "archive", 28 | "initiator": "iqn" 29 | } ] 30 | } ] 31 | } ] 32 | }''' 33 | with tempfile.NamedTemporaryFile(suffix=".tmp") as tmpfile: 34 | tmpfile.write(data) 35 | tmpfile.flush() 36 | self.content.read(tmpfile.name) 37 | assert self.content.submitted 38 | 39 | @raises(IOError) 40 | def test_read_ioerror(self): 41 | self.content.read("missing_file") 42 | 43 | @raises(RuntimeError) 44 | def test_read_runtimeerror(self): 45 | # Double comma 46 | data = '''{ "auth": [ { "host": "" } ], , 47 | "pools": [ { "gateways": [ { "host": [], "tpg": [] } ] } ] }''' 48 | with tempfile.NamedTemporaryFile(suffix=".tmp") as tmpfile: 49 | tmpfile.write(data) 50 | tmpfile.flush() 51 | self.content.read(tmpfile.name) 52 | 53 | # test_validate works in test_read 54 | 55 | def test_validate_exception(self): 56 | assert self.content.validate("{,}") == False 57 | 58 | def test_verify_mandatory_keys_pools(self): 59 | try: 60 | self.content.verify_mandatory_keys("{}") 61 | except ValueError, e: 62 | assert re.match(r"Mandatory key 'pools' is missing", str(e)) 63 | 64 | def test_verify_mandatory_keys_pool_contents(self): 65 | try: 66 | self.content.verify_mandatory_keys('{ "pools": [] }') 67 | except ValueError, e: 68 | assert re.match(r"pools have no entries", str(e)) 69 | 70 | def test_verify_mandatory_keys_gateways(self): 71 | data = '{ "pools": [ { "pool": "" } ] }' 72 | try: 73 | self.content.verify_mandatory_keys(data) 74 | except ValueError, e: 75 | assert re.match(r"Mandatory key 'gateways' is missing", str(e)) 76 | 77 | def test_verify_mandatory_keys_gateways_entries(self): 78 | data = '{ "pools": [ { "gateways": [] } ] }' 79 | try: 80 | self.content.verify_mandatory_keys(data) 81 | except ValueError, e: 82 | assert re.match(r"gateways have no entries", str(e)) 83 | 84 | 85 | def test_verify_mandatory_keys_host_or_target(self): 86 | data = '{ "pools": [ { "gateways": [ { "tpg": [] } ] } ] }' 87 | try: 88 | self.content.verify_mandatory_keys(data) 89 | except ValueError, e: 90 | assert re.match(r"Mandatory key 'host' or 'target' is missing", str(e)) 91 | 92 | def test_verify_mandatory_keys_tpg(self): 93 | data = '{ "pools": [ { "gateways": [ { "host": [] } ] } ] }' 94 | try: 95 | self.content.verify_mandatory_keys(data) 96 | except ValueError, e: 97 | assert re.match(r"Mandatory key 'tpg' is missing", str(e)) 98 | 99 | def test_verify_mandatory_keys_auth(self): 100 | data = '''{ "auth": [ { "discovery": "" } ], 101 | "pools": [ { "gateways": [ { "host": [], "tpg": [] } ] } ] }''' 102 | try: 103 | self.content.verify_mandatory_keys(data) 104 | except ValueError, e: 105 | assert re.match(r"Mandatory key 'host' or 'target' is missing from auth", str(e)) 106 | 107 | def test_remove_absent_entry_none(self): 108 | data = { "pools": [ { "pool": "rbd", "gateways": [ { "host": "igw1", "tpg": [ { "image": "archive", "initiator": "iqn.xyz" } ] } ] } ] } 109 | self.content.current = data 110 | self.content.submitted = data 111 | class Attributes: 112 | called = False 113 | def remove(self): 114 | self.called = True 115 | 116 | self.content.attr = Attributes() 117 | 118 | self.content._remove_absent_entry() 119 | assert not self.content.attr.called 120 | 121 | def test_remove_absent_entry(self): 122 | data = { "pools": [ { "pool": "rbd", "gateways": [ { "host": "igw1", "tpg": [ { "image": "archive", "initiator": "iqn.xyz" } ] }, { "host": "igw2", "tpg": [ { "image": "archive", "initiator": "iqn.wxy" } ] } ] } ] } 123 | self.content.current = data 124 | 125 | self.content.submitted = { "pools": [ { "pool": "rbd", "gateways": [ { "host": "igw1", "tpg": [ { "image": "archive", "initiator": "iqn.xyz" } ] } ] } ] } 126 | class Attributes: 127 | called = False 128 | def remove(self, pool, key): 129 | self.called = True 130 | 131 | self.content.attr = Attributes() 132 | 133 | self.content._remove_absent_entry() 134 | assert self.content.attr.called 135 | 136 | def test_write_host_exception(self): 137 | 138 | pool = {"pool": "rbd"} 139 | gateway = {"host": "igw1", "target": "iqn.xyz" } 140 | 141 | try: 142 | self.content._write_host(pool, gateway) 143 | except ValueError, e: 144 | assert re.match(r"gateway entry must contain either 'host' or 'target'", str(e)) 145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /test/test_helpers.py: -------------------------------------------------------------------------------- 1 | from lrbd import strip_comments, lstrip_spaces, check_keys, compare_settings, iqn, uniq, Common, retry 2 | from nose.tools import * 3 | import unittest 4 | import mock 5 | 6 | class HelpersTestCase(unittest.TestCase): 7 | 8 | def setUp(self): 9 | Common.config = {} 10 | 11 | def tearDown(self): 12 | Common.config = {} 13 | 14 | @mock.patch('lrbd.popen') 15 | def test_retry(self, mock_subproc_popen): 16 | retry([ "echo", "hello"]) 17 | assert mock_subproc_popen.called 18 | 19 | @raises(RuntimeError) 20 | def test_retry_failure(self): 21 | retry([ "/bin/false" ]) 22 | 23 | @raises(RuntimeError) 24 | def test_retry_failure_custom(self): 25 | retry([ "/bin/false" ], retry_errors = [ 1 ], sleep = 0.1, retries = 2) 26 | 27 | def test_strip_comments(self): 28 | assert strip_comments("# some comment\n") == "" 29 | 30 | def test_strip_comments_unchanged(self): 31 | assert strip_comments("some code\n") == "some code\n" 32 | 33 | def test_lstrip_spaces(self): 34 | assert lstrip_spaces(" " * 12) == "" 35 | 36 | def test_check_keys(self): 37 | keys = [ "a", "b", "c" ] 38 | data = { "a": "", "b": "", "c": "" } 39 | assert check_keys(keys, data, "test_check_keys") == None 40 | 41 | @raises(ValueError) 42 | def test_check_keys_exception(self): 43 | keys = [ "a", "b", "c", "d" ] 44 | data = { "a": "", "b": "", "c": "" } 45 | check_keys(keys, data, "test_check_keys") 46 | 47 | def test_compare_settings(self): 48 | keys = [ "a", "b" ] 49 | current = { "a": "apple", "b": "banana" } 50 | config = { "a": "apple", "b": "banana", "c": "cherry" } 51 | assert compare_settings(keys, current, config) 52 | 53 | def test_compare_settings_fails(self): 54 | keys = [ "a", "b" ] 55 | current = { "a": "apple", "b": "banana" } 56 | config = { "a": "apple", "b": "blueberry", "c": "cherry" } 57 | assert compare_settings(keys, current, config) == False 58 | 59 | def test_iqn(self): 60 | entry = { 'target': "def" } 61 | Common.config = { 'iqns' : [ "abc" ] } 62 | assert iqn(entry) == "def" 63 | 64 | def test_iqn_missing_target(self): 65 | entry = {} 66 | Common.config['iqns'] = [ "abc" ] 67 | #Common.config = { 'iqns' : [ "abc" ] } 68 | assert iqn(entry) == "abc" 69 | 70 | # skip test_addresses 71 | 72 | def test_uniq(self): 73 | a = [ [ "cmd1", "arg1" ], [ "cmd1", "arg1" ] ] 74 | b = [ [ "cmd1", "arg1" ] ] 75 | print uniq(a) 76 | assert uniq(a) == b 77 | -------------------------------------------------------------------------------- /test/test_images.py: -------------------------------------------------------------------------------- 1 | 2 | from lrbd import entries, Images, Common 3 | import unittest 4 | import mock 5 | 6 | class ImagesTestCase(unittest.TestCase): 7 | 8 | def setUp(self): 9 | Common.config = { 10 | "pools": [ 11 | { "pool": "rbd", 12 | "gateways": [ 13 | { "host": "igw1", "tpg": [ 14 | { "image": "archive" } 15 | ] 16 | } ] 17 | } ] } 18 | 19 | class mock_Images(Images): 20 | def __init__(self): 21 | self.mounts = {} 22 | self.i = mock_Images() 23 | 24 | @mock.patch('lrbd.popen') 25 | def test_map(self, mock_subproc_popen): 26 | self.i.map() 27 | assert mock_subproc_popen.called 28 | 29 | @mock.patch('lrbd.popen') 30 | def test_map_with_existing(self, mock_subproc_popen): 31 | self.i.mounts["rbd:city"] = "/dev/rbd0" 32 | self.i.map() 33 | assert mock_subproc_popen.called 34 | 35 | @mock.patch('lrbd.popen') 36 | def test_map_nothing(self, mock_subproc_popen): 37 | self.i.mounts["rbd:archive"] = "/dev/rbd0" 38 | self.i.map() 39 | assert not mock_subproc_popen.called 40 | 41 | @mock.patch('lrbd.popen') 42 | def test_unmap(self, mock_subproc_popen): 43 | self.i.mounts["rbd:archive"] = "/dev/rbd0" 44 | self.i.unmap() 45 | assert mock_subproc_popen.called 46 | 47 | @mock.patch('lrbd.popen') 48 | def test_unmap_nothing(self, mock_subproc_popen): 49 | self.i.unmap() 50 | assert not mock_subproc_popen.called 51 | 52 | 53 | -------------------------------------------------------------------------------- /test/test_initiatorsettings.py: -------------------------------------------------------------------------------- 1 | 2 | from lrbd import InitiatorSettings, Common, Runtime, entries 3 | from nose.tools import * 4 | import unittest, mock 5 | import re, tempfile 6 | 7 | class InitiatorSettingsTestCase(unittest.TestCase): 8 | 9 | def setUp(self): 10 | Common.config['iqns'] = [ "iqn.xyz" ] 11 | Common.config['auth'] = [ { "host": "igw1", 12 | "authentication": "acls", 13 | "acls": [{ 14 | "initiator": "iqn.abc", 15 | "attrib_nopin_timeout": "15" 16 | }] 17 | } ] 18 | Common.config['portals'] = [ { "name": "portal1", 19 | "addresses": [ 20 | "172.16.1.16" 21 | ] } ] 22 | Common.config['pools'] = [ 23 | { "pool": "rbd", 24 | "gateways": [ 25 | { "host": "igw1", "tpg": [ 26 | { "image": "archive", 27 | "initiator": "iqn.abc", 28 | "portal": "portal1" } 29 | ] 30 | } ] 31 | } ] 32 | 33 | Runtime.config['addresses'] = [ "172.16.1.16" ] 34 | Runtime.config['portals'] = {} 35 | Runtime.config['portals']["iqn.xyz"] = {} 36 | Runtime.config['portals']["iqn.xyz"]["archive"] = {} 37 | Runtime.config['portals']["iqn.xyz"]["archive"]["portal1"] = "1" 38 | 39 | def test_assign(self): 40 | class mock_InitiatorSettings(InitiatorSettings): 41 | 42 | def _tidy(self, target, entries): 43 | self.target = target 44 | self.entries = entries 45 | 46 | self.a = mock_InitiatorSettings() 47 | self.a.assign() 48 | assert self.a.target == "iqn.xyz" 49 | assert self.a.entries == [{'initiator': 'iqn.abc', 'attrib_nopin_timeout': '15'}] 50 | 51 | def test_tidy(self): 52 | class mock_InitiatorSettings(InitiatorSettings): 53 | 54 | def _save(self, target, initiator, settings): 55 | self.target = target 56 | self.initiator = initiator 57 | self.settings = settings 58 | 59 | settings = [{'initiator': 'iqn.abc', 'attrib_nopin_timeout': '15'}] 60 | self.a = mock_InitiatorSettings() 61 | self.a._tidy("iqn.xyz", settings) 62 | 63 | assert self.a.target == "iqn.xyz" 64 | assert self.a.initiator == "iqn.abc" 65 | assert self.a.settings == {'attrib_nopin_timeout': '15'} 66 | 67 | -------------------------------------------------------------------------------- /test/test_iscsi.py: -------------------------------------------------------------------------------- 1 | 2 | from lrbd import entries, Iscsi, Common, Runtime 3 | import unittest 4 | import mock, tempfile 5 | 6 | class IscsiTestCase(unittest.TestCase): 7 | 8 | def test_iscsi_default(self): 9 | Common.config = { "targets": [] } 10 | class mock_Iscsi(Iscsi): 11 | def _gen_wwn(self): 12 | pass 13 | def _assign_vendor(self): 14 | pass 15 | def disable_auto_add_default_portal(self): 16 | pass 17 | self.i = mock_Iscsi() 18 | print self.i.cmds 19 | assert self.i.cmds == [['targetcli', '/iscsi', 'create' ]] 20 | 21 | def test_iscsi_defined_target(self): 22 | Common.config = { "targets": [ { "host": "igw1", 23 | "target": "iqn.xyz" } ] } 24 | class mock_Iscsi(Iscsi): 25 | def _gen_wwn(self): 26 | pass 27 | def _assign_vendor(self): 28 | pass 29 | def disable_auto_add_default_portal(self): 30 | pass 31 | 32 | self.i = mock_Iscsi() 33 | assert self.i.cmds == [['targetcli', '/iscsi', 'create', 'iqn.xyz' ]] 34 | 35 | @mock.patch('lrbd.Popen') 36 | @mock.patch('glob.glob') 37 | def test_create_default(self, mock_subproc_glob, mock_subproc_popen): 38 | mock_subproc_popen.return_value.returncode = 0 39 | 40 | Common.config = { "targets": [ { "host": "igw1", 41 | "target": "iqn.xyz" } ] } 42 | mock_subproc_glob.return_value = [ "/some/path/name" ] 43 | class mock_Iscsi(Iscsi): 44 | def _gen_wwn(self): 45 | pass 46 | def _assign_vendor(self): 47 | pass 48 | def disable_auto_add_default_portal(self): 49 | pass 50 | self.i = mock_Iscsi() 51 | #self.i.cmds = [[ "targetcli", "hello" ]] 52 | self.i.create() 53 | assert (mock_subproc_popen.called and 54 | Common.config['iqns'] == [ "iqn.xyz" ]) 55 | 56 | @mock.patch('lrbd.Popen') 57 | def test_create(self, mock_subproc_popen): 58 | mock_subproc_popen.return_value.returncode = 0 59 | Common.config = { "targets": [ { "host": "igw1", 60 | "target": "iqn.xyz" } ] } 61 | class mock_Iscsi(Iscsi): 62 | def _gen_wwn(self): 63 | pass 64 | def _assign_vendor(self): 65 | pass 66 | def disable_auto_add_default_portal(self): 67 | pass 68 | self.i = mock_Iscsi() 69 | self.i.cmds = [[ "targetcli", "hello" ]] 70 | self.i.create() 71 | assert mock_subproc_popen.called 72 | 73 | @mock.patch('lrbd.Runtime.backstore') 74 | @mock.patch('lrbd.Runtime.core') 75 | @mock.patch('os.path.isfile') 76 | def test_assign_vendor(self, mock_backstore, mock_core, mock_isfile): 77 | 78 | Common.config = { "targets": [ { "host": "igw1", 79 | "target": "iqn.xyz" } ] } 80 | Common.config['pools'] = [ 81 | { "pool": "rbd", 82 | "gateways": [ 83 | { "host": "igw1", "tpg": [ 84 | { "image": "archive" } 85 | ] 86 | } ] 87 | } ] 88 | 89 | with tempfile.NamedTemporaryFile(suffix=".tmp") as tmpfile: 90 | mock_backstore.return_value = "archive" 91 | mock_core.return_value = [ tmpfile.name ] 92 | mock_isfile.return_value = True 93 | 94 | class mock_Iscsi(Iscsi): 95 | def _arrange(self): 96 | pass 97 | def disable_auto_add_default_portal(self): 98 | pass 99 | 100 | 101 | self.i = mock_Iscsi() 102 | self.i._assign_vendor() 103 | tmpfile.flush() 104 | contents = tmpfile.read().strip() 105 | assert contents == "SUSE" 106 | 107 | -------------------------------------------------------------------------------- /test/test_luns.py: -------------------------------------------------------------------------------- 1 | 2 | from lrbd import Luns, Common, Runtime, entries 3 | import unittest, mock 4 | import re, tempfile 5 | import logging 6 | 7 | class LunsTestCase(unittest.TestCase): 8 | 9 | def setUp(self): 10 | Common.config = { 11 | "iqns": [ "iqn.xyz" ], 12 | "pools": [ 13 | { "pool": "rbd", 14 | "gateways": [ 15 | { "host": "igw1", "tpg": [ 16 | { "image": "archive" } 17 | ] 18 | } ] 19 | } ] } 20 | 21 | def test_lun(self): 22 | class mock_Luns(Luns): 23 | 24 | def _find(self): 25 | pass 26 | 27 | def _cmd(self, target, tpg, address): 28 | self.called = " ".join([ target, str(tpg), address ]) 29 | 30 | self.l = mock_Luns(None) 31 | assert self.l.called == "iqn.xyz 1 archive" 32 | 33 | @mock.patch('glob.glob') 34 | def test_find(self, mock_subproc_glob): 35 | mock_subproc_glob = [] 36 | class mock_Luns(Luns): 37 | 38 | def _cmd(self, target, tpg, address): 39 | self.called = " ".join([ target, str(tpg), address ]) 40 | 41 | self.l = mock_Luns(None) 42 | assert self.l.exists == {'iqn.xyz': {}} 43 | 44 | @mock.patch('glob.glob') 45 | def test_find_existing(self, mock_subproc_glob): 46 | 47 | class mock_Luns(Luns): 48 | 49 | def _cmd(self, target, tpg, address): 50 | self.called = " ".join([ target, str(tpg), address ]) 51 | 52 | with tempfile.NamedTemporaryFile(suffix="._1_1_1_1_1_1_tmp") as tmpfile: 53 | tmpfile.write("/dev/rbd/rbd/archive\n") 54 | tmpfile.flush() 55 | mock_subproc_glob.return_value = [ tmpfile.name ] 56 | self.l = mock_Luns(None) 57 | assert self.l.exists == {'iqn.xyz': {'1': ['archive']}} 58 | 59 | 60 | def test_cmd_for_rbd(self): 61 | 62 | Runtime.config['backstore'] = "rbd" 63 | class mock_Luns(Luns): 64 | 65 | def _find(self): 66 | pass 67 | 68 | class mock_LunAssignment(object): 69 | def assign(self, target, tpg, image, lun): 70 | pass 71 | 72 | def assigned(self, target, image): 73 | pass 74 | 75 | logging.disable(logging.DEBUG) 76 | _la = mock_LunAssignment() 77 | self.l = mock_Luns(_la) 78 | print self.l.unassigned 79 | assert self.l.unassigned == [ ['targetcli', '/iscsi/iqn.xyz/tpg1/luns', 'create', '/backstores/rbd/rbd-archive'] ] 80 | 81 | 82 | 83 | @mock.patch('lrbd.Popen') 84 | def test_create_nothing(self, mock_subproc_popen): 85 | 86 | mock_subproc_popen.return_value.returncode = 0 87 | class mock_Luns(Luns): 88 | 89 | def _find(self): 90 | pass 91 | 92 | def _cmd(self, target, tpg, address): 93 | self.called = " ".join([ target, str(tpg), address ]) 94 | 95 | def disable_auto_add_mapped_luns(self): 96 | pass 97 | 98 | self.l = mock_Luns(None) 99 | self.l.cmds = [[ "targetcli", "hello" ]] 100 | self.l.create() 101 | 102 | assert mock_subproc_popen.called 103 | 104 | @mock.patch('lrbd.Popen') 105 | def test_create(self, mock_subproc_popen): 106 | 107 | mock_subproc_popen.return_value.returncode = 0 108 | class mock_Luns(Luns): 109 | 110 | def _find(self): 111 | pass 112 | 113 | def disable_auto_add_mapped_luns(self): 114 | pass 115 | 116 | class mock_LunAssignment(object): 117 | def assign(self, target, tpg, image, lun): 118 | pass 119 | 120 | def assigned(self, target, image): 121 | pass 122 | 123 | _la = mock_LunAssignment() 124 | self.l = mock_Luns(_la) 125 | self.l.cmds = [[ "targetcli", "hello" ]] 126 | self.l.create() 127 | 128 | assert mock_subproc_popen.called 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /test/test_main.py: -------------------------------------------------------------------------------- 1 | 2 | from lrbd import main, Configs, Images 3 | import unittest, mock 4 | import re, tempfile 5 | import argparse 6 | 7 | class MainTestCase(unittest.TestCase): 8 | 9 | def setUp(self): 10 | self.args = argparse.Namespace() 11 | self.args.config = None 12 | self.args.ceph = "/etc/motd" 13 | self.args.host = None 14 | self.args.verbose = False 15 | self.args.debug = False 16 | self.args.name = "client.admin" 17 | self.args.pools = [] 18 | 19 | @mock.patch('lrbd.Configs.wipe') 20 | def test_main_wipe(self, mock_subproc_wipe): 21 | self.args.wipe = True 22 | main(self.args) 23 | assert mock_subproc_wipe.called 24 | 25 | @mock.patch('lrbd.Configs.clear') 26 | def test_main_clear(self, mock_subproc_clear): 27 | self.args.wipe = False 28 | self.args.clear = True 29 | self.args.unmap = False 30 | main(self.args) 31 | assert mock_subproc_clear.called 32 | 33 | @mock.patch('lrbd.Configs.clear') 34 | @mock.patch('lrbd.Images.__init__') 35 | @mock.patch('lrbd.Images.unmap') 36 | def test_main_clear_and_unmap(self, mock_clear, mock_init, mock_unmap): 37 | self.args.wipe = False 38 | self.args.clear = True 39 | self.args.unmap = True 40 | mock_init.return_value = None 41 | main(self.args) 42 | assert (mock_clear.called and mock_unmap.called) 43 | 44 | @mock.patch('lrbd.Images') 45 | def test_main_unmap(self, mock_Images): 46 | self.args.wipe = False 47 | self.args.clear = False 48 | self.args.unmap = True 49 | main(self.args) 50 | assert mock_Images.called 51 | 52 | @mock.patch('lrbd.Configs.wipe') 53 | @mock.patch('lrbd.Content') 54 | def test_main_file(self, mock_wipe, mock_Content): 55 | self.args.wipe = False 56 | self.args.clear = False 57 | self.args.unmap = False 58 | self.args.file = True 59 | main(self.args) 60 | assert (mock_wipe.called and mock_Content.called) 61 | 62 | @mock.patch('lrbd.Content') 63 | def test_main_add(self, mock_Content): 64 | self.args.wipe = False 65 | self.args.clear = False 66 | self.args.unmap = False 67 | self.args.file = False 68 | self.args.add = True 69 | main(self.args) 70 | assert mock_Content.called 71 | 72 | @mock.patch('lrbd.Configs') 73 | def test_main_output(self, mock_Configs): 74 | self.args.wipe = False 75 | self.args.clear = False 76 | self.args.unmap = False 77 | self.args.file = False 78 | self.args.add = False 79 | self.args.output = True 80 | main(self.args) 81 | assert mock_Configs.called 82 | 83 | @mock.patch('lrbd.Configs') 84 | @mock.patch('lrbd.Content') 85 | def test_main_edit(self, mock_Configs, mock_Content): 86 | self.args.wipe = False 87 | self.args.clear = False 88 | self.args.unmap = False 89 | self.args.file = False 90 | self.args.add = False 91 | self.args.output = False 92 | self.args.edit = True 93 | self.args.editor = None 94 | self.args.migrate = False 95 | main(self.args) 96 | assert (mock_Configs.called and mock_Content.called) 97 | 98 | @mock.patch('lrbd.Configs') 99 | def test_main_local(self, mock_Configs): 100 | self.args.wipe = False 101 | self.args.clear = False 102 | self.args.unmap = False 103 | self.args.file = False 104 | self.args.add = False 105 | self.args.output = False 106 | self.args.edit = False 107 | self.args.local = True 108 | self.args.migrate = False 109 | main(self.args) 110 | assert mock_Configs.called 111 | 112 | @mock.patch('lrbd.Configs') 113 | @mock.patch('lrbd.Images') 114 | @mock.patch('lrbd.Backstores') 115 | @mock.patch('lrbd.Iscsi') 116 | @mock.patch('lrbd.TPGs') 117 | @mock.patch('lrbd.Luns') 118 | @mock.patch('lrbd.TPGattributes') 119 | @mock.patch('lrbd.Portals') 120 | @mock.patch('lrbd.Acls') 121 | @mock.patch('lrbd.Map') 122 | @mock.patch('lrbd.Auth') 123 | def test_main_default(self, mock_Configs, mock_Images, mock_Backstores, mock_Iscsi, mock_TPGs, mock_Luns, mock_Portals, mock_TPGattributes, mock_Acls, mock_Map, mock_Auth): 124 | self.args.wipe = False 125 | self.args.clear = False 126 | self.args.unmap = False 127 | self.args.file = False 128 | self.args.add = False 129 | self.args.output = False 130 | self.args.edit = False 131 | self.args.local = False 132 | self.args.migrate = False 133 | self.args.backstore = "iblock" 134 | main(self.args) 135 | assert (mock_Configs.called and 136 | mock_Images.called and 137 | mock_Backstores.called and 138 | mock_Iscsi.called and 139 | mock_TPGs.called and 140 | mock_Luns.called and 141 | mock_Portals.called and 142 | mock_TPGattributes.called and 143 | mock_Acls.called and 144 | mock_Map.called and 145 | mock_Auth.called) 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /test/test_map.py: -------------------------------------------------------------------------------- 1 | 2 | from lrbd import Map, Common, Runtime, entries 3 | from nose.tools import * 4 | import unittest, mock 5 | import re, tempfile 6 | 7 | class MapTestCase(unittest.TestCase): 8 | 9 | def setUp(self): 10 | Common.config = { 11 | "iqns": [ "iqn.xyz" ], 12 | "auth": [ { "host": "igw1", "authentication": "acls" } ], 13 | "pools": [ 14 | { "pool": "rbd", 15 | "gateways": [ 16 | { "host": "igw1", "tpg": [ 17 | { "image": "archive", "initiator": "iqn.abc" } 18 | ] 19 | } ] 20 | } ] } 21 | 22 | def test_map(self): 23 | 24 | class mock_Map(Map): 25 | 26 | def _lun(self, target, tpg, image): 27 | return("1") 28 | 29 | def _check(self, target, tpg, initiator): 30 | pass 31 | 32 | def _cmd(self, target, tpg, initiator, lun): 33 | self.called = " ".join([ target, str(tpg), initiator, lun ]) 34 | 35 | self.m = mock_Map() 36 | assert self.m.called == "iqn.xyz 1 iqn.abc 1" 37 | 38 | # Something is seriously wrong with the patching... seems to be applied 39 | # to both return values. The result does test the success condition. 40 | @mock.patch('os.path.basename') 41 | @mock.patch('glob.glob') 42 | def test_lun(self, mock_os_path_basename, mock_subproc_glob): 43 | 44 | #mock_subproc_glob.return_value = 45 | mock_os_path_basename.return_value = [ "/s/k/c/t/i/i/t/l/lun_0/rbd-archive" ] 46 | 47 | class mock_Map(Map): 48 | 49 | def _cmd(self, target, tpg, initiator, lun): 50 | self.called = " ".join([ target, str(tpg), initiator, lun ]) 51 | 52 | 53 | self.m = mock_Map() 54 | assert self.m.called == "iqn.xyz 1 iqn.abc rbd-archive" 55 | 56 | @raises(ValueError) 57 | @mock.patch('glob.glob') 58 | def test_lun_exception(self, mock_subproc_glob): 59 | 60 | mock_subproc_glob.return_value = [] 61 | 62 | class mock_Map(Map): 63 | 64 | def _cmd(self, target, tpg, initiator, lun): 65 | self.called = " ".join([ target, str(tpg), initiator, lun ]) 66 | 67 | self.m = mock_Map() 68 | 69 | @mock.patch('glob.glob') 70 | def test_check(self, mock_subproc_glob): 71 | 72 | mock_subproc_glob.return_value = [ "/some/path" ] 73 | class mock_Map(Map): 74 | 75 | def _lun(self, target, tpg, image): 76 | return("1") 77 | 78 | def _cmd(self, target, tpg, initiator, lun): 79 | self.called = " ".join([ target, str(tpg), initiator, lun ]) 80 | 81 | self.m = mock_Map() 82 | assert self.m.called == "iqn.xyz 1 iqn.abc 1" 83 | 84 | @raises(ValueError) 85 | @mock.patch('glob.glob') 86 | def test_check_exception(self, mock_subproc_glob): 87 | 88 | mock_subproc_glob.return_value = [] 89 | class mock_Map(Map): 90 | 91 | def _lun(self, target, tpg, image): 92 | return("1") 93 | 94 | def _cmd(self, target, tpg, initiator, lun): 95 | self.called = " ".join([ target, str(tpg), initiator, lun ]) 96 | 97 | self.m = mock_Map() 98 | 99 | @mock.patch('glob.glob') 100 | def test_cmd(self, mock_subproc_glob): 101 | 102 | mock_subproc_glob.return_value = [ ] 103 | class mock_Map(Map): 104 | 105 | def _lun(self, target, tpg, image): 106 | return("1") 107 | 108 | def _check(self, target, tpg, initiator): 109 | pass 110 | 111 | self.m = mock_Map() 112 | assert self.m.cmds == [['targetcli', '/iscsi/iqn.xyz/tpg1/acls/iqn.abc', 'create', '1', '1']] 113 | 114 | @mock.patch('glob.glob') 115 | def test_cmd_does_nothing(self, mock_subproc_glob): 116 | 117 | mock_subproc_glob.return_value = [ "/some/path" ] 118 | class mock_Map(Map): 119 | 120 | def _lun(self, target, tpg, image): 121 | return("1") 122 | 123 | def _check(self, target, tpg, initiator): 124 | pass 125 | 126 | self.m = mock_Map() 127 | assert not self.m.cmds 128 | 129 | @mock.patch('lrbd.Popen') 130 | def test_map(self, mock_subproc_popen): 131 | 132 | mock_subproc_popen.return_value.returncode = 0 133 | class mock_Map(Map): 134 | 135 | def _lun(self, target, tpg, image): 136 | return("1") 137 | 138 | def _check(self, target, tpg, initiator): 139 | pass 140 | 141 | def _cmd(self, target, tpg, initiator, lun): 142 | self.called = " ".join([ target, str(tpg), initiator, lun ]) 143 | 144 | self.m = mock_Map() 145 | self.m.cmds = [ [ "targetcli", "hello" ] ] 146 | self.m.map() 147 | assert mock_subproc_popen.called 148 | 149 | @mock.patch('lrbd.Popen') 150 | def test_map_does_nothing(self, mock_subproc_popen): 151 | 152 | mock_subproc_popen.return_value.returncode = 0 153 | class mock_Map(Map): 154 | 155 | def _lun(self, target, tpg, image): 156 | return("1") 157 | 158 | def _check(self, target, tpg, initiator): 159 | pass 160 | 161 | def _cmd(self, target, tpg, initiator, lun): 162 | self.called = " ".join([ target, str(tpg), initiator, lun ]) 163 | 164 | self.m = mock_Map() 165 | self.m.map() 166 | assert mock_subproc_popen.called 167 | -------------------------------------------------------------------------------- /test/test_pools.py: -------------------------------------------------------------------------------- 1 | 2 | from lrbd import Pools 3 | import unittest 4 | import re, tempfile 5 | 6 | class PoolsTestCase(unittest.TestCase): 7 | 8 | def setUp(self): 9 | self.p = Pools() 10 | self.p.add("swimming") 11 | 12 | def test_add(self): 13 | assert self.p.pools[0]['pool'] == "swimming" 14 | 15 | def test_append(self): 16 | data = { 'gateways': [] } 17 | self.p.append("swimming", data) 18 | self.p.display() 19 | assert self.p.pools[0]['pool'] == "swimming" 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /test/test_portals.py: -------------------------------------------------------------------------------- 1 | 2 | from lrbd import Portals, Common, Runtime 3 | from nose.tools import * 4 | import unittest, mock 5 | import re, tempfile 6 | 7 | class PortalsTestCase(unittest.TestCase): 8 | 9 | def setUp(self): 10 | Common.config['iqns'] = [ "iqn.xyz" ] 11 | Common.config['portals'] = [ { "name": "portal1", 12 | "addresses": [ 13 | "172.16.1.16" 14 | ] } ] 15 | Runtime.config = {} 16 | Runtime.config['addresses'] = [ "172.16.1.16" ] 17 | Runtime.config['portals'] = {} 18 | Runtime.config['portals']["iqn.xyz"] = {} 19 | Runtime.config['portals']["iqn.xyz"]["archive"] = {} 20 | Runtime.config['portals']["iqn.xyz"]["archive"]["portal1"] = "1" 21 | 22 | 23 | def test_portal_default(self): 24 | Common.config['iqns'] = [ "iqn.xyz" ] 25 | Common.config['portals'] = [] 26 | class mock_Portals(Portals): 27 | 28 | called = False 29 | 30 | def _cmd(self, target, tpg, address): 31 | self.called = True 32 | 33 | self.pt = mock_Portals() 34 | assert self.pt.called 35 | 36 | def test_portal(self): 37 | 38 | class mock_Portals(Portals): 39 | 40 | 41 | def _entries(self): 42 | yield("iqn.xyz", "archive", "portal1", Common.config['portals'][0]) 43 | 44 | def _cmd(self, target, tpg, address): 45 | self.called = " ".join([ target, tpg, address ]) 46 | 47 | self.pt = mock_Portals() 48 | assert self.pt.called == "iqn.xyz 1 172.16.1.16" 49 | 50 | def test_portal_remote(self): 51 | Common.config['portals'] = [ { "name": "portal2", 52 | "addresses": [ 53 | "172.16.1.17" 54 | ] } ] 55 | Runtime.config = {} 56 | Runtime.config['portals'] = {} 57 | Runtime.config['portals']["iqn.xyz"] = {} 58 | Runtime.config['portals']["iqn.xyz"]["archive"] = {} 59 | Runtime.config['portals']["iqn.xyz"]["archive"]["portal2"] = "2" 60 | 61 | class mock_Portals(Portals): 62 | 63 | 64 | def _entries(self): 65 | yield("iqn.xyz", "archive", "portal2", Common.config['portals'][0]) 66 | 67 | def _cmd(self, target, tpg, address): 68 | self.called = " ".join([ target, tpg, address ]) 69 | 70 | self.pt = mock_Portals() 71 | assert self.pt.called == "iqn.xyz 2 172.16.1.17" 72 | 73 | 74 | def test_entries(self): 75 | 76 | class mock_Portals(Portals): 77 | 78 | def _cmd(self, target, tpg, address): 79 | self.called = " ".join([ target, tpg, address ]) 80 | 81 | self.pt = mock_Portals() 82 | assert self.pt.called == "iqn.xyz 1 172.16.1.16" 83 | 84 | @raises(ValueError) 85 | def test_entries_exception(self): 86 | del Common.config 87 | Common.config = {} 88 | Common.config['iqns'] = [ "iqn.xyz" ] 89 | Common.config['portals'] = [ { "name": "portal99" } ] 90 | 91 | class mock_Portals(Portals): 92 | 93 | def _cmd(self, target, tpg, address): 94 | self.called = " ".join([ target, tpg, address ]) 95 | 96 | self.pt = mock_Portals() 97 | 98 | 99 | @mock.patch('glob.glob') 100 | def test_portal_remote_does_nothing(self, mock_subproc_glob): 101 | Runtime.config['addresses'] = [ "172.16.1.17" ] 102 | 103 | mock_subproc_glob.return_value = [ "/some/path" ] 104 | 105 | self.pt = Portals() 106 | assert self.pt.cmds == [] 107 | 108 | @mock.patch('lrbd.Popen') 109 | def test_create(self, mock_subproc_popen): 110 | mock_subproc_popen.return_value.returncode = 0 111 | Runtime.config['addresses'] = [ "172.16.1.17" ] 112 | Runtime.config['portals'] = {} 113 | Runtime.config['portals']["iqn.xyz"] = {} 114 | Runtime.config['portals']["iqn.xyz"]["archive"] = {} 115 | Runtime.config['portals']["iqn.xyz"]["archive"]["portal1"] = "1" 116 | 117 | self.pt = Portals() 118 | self.pt.cmds = [[ "targetcli", "hello" ]] 119 | self.pt.create() 120 | assert mock_subproc_popen.called 121 | 122 | 123 | -------------------------------------------------------------------------------- /test/test_portalsecton.py: -------------------------------------------------------------------------------- 1 | 2 | from lrbd import * 3 | import unittest 4 | #import re, tempfile 5 | 6 | class PortalSectionTestCase(unittest.TestCase): 7 | 8 | def setUp(self): 9 | self.pt = PortalSection() 10 | data = [ { "name": "portal1", "addresses": [ "172.16.1.16" ] } ] 11 | self.pt.add(data) 12 | 13 | def test_add(self): 14 | self.pt.display() 15 | assert self.pt.portals[0]['name'] == "portal1" 16 | 17 | def test_purge(self): 18 | self.pt.purge("portal2") 19 | self.pt.display() 20 | assert not self.pt.portals 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /test/test_sysconfig.py: -------------------------------------------------------------------------------- 1 | 2 | from lrbd import sysconfig_options 3 | import unittest 4 | import re, tempfile 5 | 6 | class SysconfigTestCase(unittest.TestCase): 7 | 8 | def test_sysconfig_options(self): 9 | data = '''LRBD_OPTIONS="-v"''' 10 | with tempfile.NamedTemporaryFile(suffix=".tmp") as tmpfile: 11 | tmpfile.write(data) 12 | tmpfile.flush() 13 | result = sysconfig_options(tmpfile.name) 14 | print result 15 | assert result == ['-v'] 16 | 17 | def test_sysconfig_options_missing_variable(self): 18 | data = '''#Just a comment''' 19 | with tempfile.NamedTemporaryFile(suffix=".tmp") as tmpfile: 20 | tmpfile.write(data) 21 | tmpfile.flush() 22 | result = sysconfig_options(tmpfile.name) 23 | assert result == [] 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /test/test_targets.py: -------------------------------------------------------------------------------- 1 | 2 | from lrbd import Common, Targets 3 | import unittest 4 | #import re, tempfile 5 | 6 | class TargetsTestCase(unittest.TestCase): 7 | 8 | def setUp(self): 9 | self.t = Targets() 10 | self.data = [ { "host": "igw1", "target": "iqn.xyz" } ] 11 | 12 | def test_add(self): 13 | self.t.add(self.data) 14 | self.t.display() 15 | assert self.t.targets[0]['host'] == "igw1" 16 | 17 | def test_list(self): 18 | data = [ { "hosts": [ { "host": "igw1"}, { "host": "igw2" } ], 19 | "target": "iqn.xyz" } ] 20 | self.t.add(data) 21 | Common.hostname = "igw1" 22 | targets = self.t.list() 23 | self.t.display() 24 | assert targets[0] == "iqn.xyz" 25 | 26 | 27 | def test_purge(self): 28 | self.t.add(self.data) 29 | Common.hostname = "igw2" 30 | self.t.purge() 31 | self.t.display() 32 | assert not self.t.targets 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /test/test_tpgs.py: -------------------------------------------------------------------------------- 1 | 2 | from lrbd import entries, TPGs, Common, Runtime 3 | from nose.tools import * 4 | import tempfile 5 | import unittest 6 | import mock 7 | import logging 8 | 9 | class TPGsTestCase(unittest.TestCase): 10 | 11 | def setUp(self): 12 | Common.config = { 13 | "pools": [ 14 | { "pool": "rbd", 15 | "gateways": [ 16 | { "host": "igw1", "tpg": [ 17 | { "image": "archive" } 18 | ] 19 | } ] 20 | } ] } 21 | 22 | 23 | @mock.patch('lrbd.addresses') 24 | def test_tpgs(self, mock_subproc_addresses): 25 | class mock_TPGs(TPGs): 26 | 27 | def _add(self): 28 | pass 29 | 30 | def _remote(self): 31 | pass 32 | 33 | def _add_target(self): 34 | pass 35 | 36 | def disable_auto_add_default_portal(self): 37 | pass 38 | 39 | class Portal_Index(object): 40 | def portals(self): 41 | pass 42 | 43 | _pi = Portal_Index() 44 | self.t = mock_TPGs(None, _pi, None) 45 | assert ('addresses' in Runtime.config and 46 | 'portals' in Runtime.config) 47 | 48 | def test_add_none(self): 49 | class mock_TPGs(TPGs): 50 | 51 | def _add(self): 52 | pass 53 | 54 | def _check_portal(self): 55 | pass 56 | 57 | def disable_auto_add_default_portal(self): 58 | pass 59 | 60 | 61 | class Portal_Index(object): 62 | def portals(self): 63 | pass 64 | 65 | _pi = Portal_Index() 66 | self.t = mock_TPGs(None, _pi, None) 67 | assert not self.t.cmds 68 | 69 | def test_add(self): 70 | Common.config = { 71 | "iqns": [ "iqn.xyz" ], 72 | "pools": [ 73 | { "pool": "rbd", 74 | "gateways": [ 75 | { "host": "igw1", "tpg": [ 76 | { "image": "archive", "portal": "portal1" } 77 | ] 78 | } ] 79 | } ] } 80 | class mock_TPGs(TPGs): 81 | 82 | def _remote(self): 83 | pass 84 | 85 | def _check_portal(self, name): 86 | pass 87 | 88 | def _add_host(self, entry, target): 89 | pass 90 | 91 | def disable_auto_add_default_portal(self): 92 | pass 93 | 94 | class Portal_Index(object): 95 | def portals(self): 96 | pass 97 | def add(self, target, image): 98 | pass 99 | 100 | class TPG_Counter(object): 101 | def reset_all(self): 102 | pass 103 | 104 | def add(self, target): 105 | pass 106 | 107 | _pi = Portal_Index() 108 | _tc = TPG_Counter() 109 | logging.disable(logging.DEBUG) 110 | self.t = mock_TPGs(_tc, _pi, None) 111 | assert (self.t.cmds == []) 112 | 113 | def test_check_portal(self): 114 | Common.config['portals'] = [ { "name": "portal1" } ] 115 | class mock_TPGs(TPGs): 116 | 117 | def _add(self): 118 | pass 119 | 120 | def _remote(self): 121 | pass 122 | 123 | def disable_auto_add_default_portal(self): 124 | pass 125 | 126 | class Portal_Index(object): 127 | def portals(self): 128 | pass 129 | 130 | _pi = Portal_Index() 131 | self.t = mock_TPGs(None, _pi, None) 132 | assert self.t._check_portal("portal1") == None 133 | 134 | @raises(ValueError) 135 | def test_check_portal_undefined(self): 136 | Common.config['portals'] = [ { "name": "portal1" } ] 137 | class mock_TPGs(TPGs): 138 | 139 | def _add(self): 140 | pass 141 | 142 | def _remote(self): 143 | pass 144 | 145 | def disable_auto_add_default_portal(self): 146 | pass 147 | 148 | class Portal_Index(object): 149 | def portals(self): 150 | pass 151 | 152 | _pi = Portal_Index() 153 | self.t = mock_TPGs(None, _pi, None) 154 | self.t._check_portal("portal2") 155 | 156 | @mock.patch('glob.glob') 157 | def test_cmd(self, mock_subproc_glob): 158 | class mock_TPGs(TPGs): 159 | 160 | def _add(self): 161 | pass 162 | 163 | def _remote(self): 164 | pass 165 | 166 | def disable_auto_add_default_portal(self): 167 | pass 168 | 169 | class Portal_Index(object): 170 | def portals(self): 171 | pass 172 | 173 | _pi = Portal_Index() 174 | self.t = mock_TPGs(None, _pi, None) 175 | mock_subproc_glob.return_value = [] 176 | result = self.t._cmd("iqn.xyz", "2") 177 | assert result == ['targetcli', '/iscsi/iqn.xyz', 'create 2'] 178 | 179 | @mock.patch('glob.glob') 180 | def test_cmd_returns_empty(self, mock_subproc_glob): 181 | class mock_TPGs(TPGs): 182 | 183 | def _add(self): 184 | pass 185 | 186 | def _remote(self): 187 | pass 188 | 189 | def disable_auto_add_default_portal(self): 190 | pass 191 | 192 | class Portal_Index(object): 193 | def portals(self): 194 | pass 195 | 196 | _pi = Portal_Index() 197 | self.t = mock_TPGs(None, _pi, None) 198 | mock_subproc_glob.return_value = "/some/path" 199 | result = self.t._cmd("iqn.xyz", "2") 200 | assert result == [] 201 | 202 | @mock.patch('lrbd.Popen') 203 | def test_create(self, mock_popen): 204 | 205 | mock_popen.return_value.returncode = 0 206 | 207 | class mock_TPGs(TPGs): 208 | 209 | def _add(self): 210 | pass 211 | 212 | def _remote(self): 213 | pass 214 | 215 | def disable_auto_add_default_portal(self): 216 | pass 217 | 218 | class Portal_Index(object): 219 | def portals(self): 220 | pass 221 | 222 | class TargetcliDispatcher: 223 | 224 | def queue_cmd(self, cmd): 225 | pass 226 | 227 | def flush_close(self): 228 | pass 229 | 230 | _pi = Portal_Index() 231 | self.t = mock_TPGs(None, _pi, None) 232 | self.t.cmds = [ [ "targetcli", "hello" ] ] 233 | self.t.create() 234 | 235 | assert mock_popen.called 236 | 237 | 238 | 239 | 240 | 241 | --------------------------------------------------------------------------------