Merge the tip of origin/release/proposed/2019.2.0 into origin/release/2019.2.0
1f165df Fix typo for Ceph errorMsg call
32b62ea Fix check for empty list
365eb25 Drop not needed ceph connectOS function from installClients stage
83bf4c2 Fixup typo in call for ceph.installClient()
0e12ee6 move function to ceph class
Change-Id: If27afab562cfc4de8c9ec5a478cddefeec42e11c
diff --git a/src/com/mirantis/mk/Ceph.groovy b/src/com/mirantis/mk/Ceph.groovy
index 8660233..72e644f 100644
--- a/src/com/mirantis/mk/Ceph.groovy
+++ b/src/com/mirantis/mk/Ceph.groovy
@@ -1,103 +1,543 @@
package com.mirantis.mk
/**
+ * Install and configure ceph clients
*
- * Ceph functions
- *
+ * @param master Salt connection object
+ * @param extra_tgt Extra targets for compound
*/
+def installClient(master, extra_tgt='') {
+ def salt = new Salt()
+
+ // install Ceph Radosgw
+ installRgw(master, "I@ceph:radosgw", extra_tgt)
+
+ // setup keyring for Openstack services
+ salt.enforceStateWithTest([saltId: master, target: "I@ceph:common and I@glance:server $extra_tgt", state: ['ceph.common', 'ceph.setup.keyring']])
+ salt.enforceStateWithTest([saltId: master, target: "I@ceph:common and I@cinder:controller $extra_tgt", state: ['ceph.common', 'ceph.setup.keyring']])
+ salt.enforceStateWithTest([saltId: master, target: "I@ceph:common and I@nova:compute $extra_tgt", state: ['ceph.common', 'ceph.setup.keyring']])
+ salt.enforceStateWithTest([saltId: master, target: "I@ceph:common and I@gnocchi:server $extra_tgt", state: ['ceph.common', 'ceph.setup.keyring']])
+}
/**
- * Ceph health check
+ * Install and configure ceph monitor on target
*
+ * @param master Salt connection object
+ * @param target Target specification, compliance to compound matcher in salt
+ * @param extra_tgt Extra targets for compound
*/
-def waitForHealthy(master, target, flags=[], count=0, attempts=300) {
- def common = new com.mirantis.mk.Common()
- def salt = new com.mirantis.mk.Salt()
- // wait for healthy cluster
- while (count < attempts) {
- def health = salt.cmdRun(master, target, 'ceph health')['return'][0].values()[0]
- if (health.contains('HEALTH_OK')) {
- common.infoMsg('Cluster is healthy')
- break
- } else {
- for (flag in flags) {
- if (health.contains(flag + ' flag(s) set') && !(health.contains('down'))) {
- common.infoMsg('Cluster is healthy')
- return
+def installMon(master, target="I@ceph:mon", extra_tgt='') {
+ def salt = new Salt()
+
+ salt.enforceState([saltId: master, target: "$target $extra_tgt", state: 'salt.minion.grains'])
+
+ // TODO: can we re-add cmn01 with proper keyrings?
+ // generate keyrings
+ if(salt.testTarget(master, "( I@ceph:mon:keyring:mon or I@ceph:common:keyring:admin ) $extra_tgt")) {
+ salt.enforceState([saltId: master, target: "( I@ceph:mon:keyring:mon or I@ceph:common:keyring:admin ) $extra_tgt", state: 'ceph.mon'])
+ salt.runSaltProcessStep(master, "I@ceph:mon $extra_tgt", 'saltutil.sync_grains')
+ salt.runSaltProcessStep(master, "( I@ceph:mon:keyring:mon or I@ceph:common:keyring:admin ) $extra_tgt", 'mine.update')
+
+ // on target nodes mine is used to get pillar from 'ceph:common:keyring:admin' via grain.items
+ // we need to refresh all pillar/grains to make data sharing work correctly
+ salt.fullRefresh(master, "( I@ceph:mon:keyring:mon or I@ceph:common:keyring:admin ) $extra_tgt")
+
+ sleep(5)
+ }
+ // install Ceph Mons
+ salt.enforceState([saltId: master, target: "I@ceph:mon $extra_tgt", state: 'ceph.mon'])
+ salt.enforceStateWithTest([saltId: master, target: "I@ceph:mgr $extra_tgt", state: 'ceph.mgr'])
+
+ // update config
+ salt.enforceState([saltId: master, target: "I@ceph:common $extra_tgt", state: 'ceph.common'])
+}
+
+/**
+ * Install and configure osd daemons on target
+ *
+ * @param master Salt connection object
+ * @param target Target specification, compliance to compound matcher in salt
+ * @param extra_tgt Extra targets for compound
+ */
+def installOsd(master, target="I@ceph:osd", setup=true, extra_tgt='') {
+ def salt = new Salt()
+ def orchestrate = new Orchestrate()
+
+ // install Ceph OSDs
+ salt.enforceState([saltId: master, target: target, state: ['linux.storage','ceph.osd']])
+ salt.runSaltProcessStep(master, "I@ceph:osd $extra_tgt", 'saltutil.sync_grains')
+ salt.enforceState([saltId: master, target: target, state: 'ceph.osd.custom'])
+ salt.runSaltProcessStep(master, "I@ceph:osd $extra_tgt", 'saltutil.sync_grains')
+ salt.runSaltProcessStep(master, "I@ceph:osd $extra_tgt", 'mine.update')
+
+ // setup pools, keyrings and maybe crush
+ if(salt.testTarget(master, "I@ceph:setup $extra_tgt") && setup) {
+ orchestrate.installBackup(master, 'ceph')
+ salt.enforceState([saltId: master, target: "I@ceph:setup $extra_tgt", state: 'ceph.setup'])
+ }
+}
+
+/**
+ * Install and configure rgw service on target
+ *
+ * @param master Salt connection object
+ * @param target Target specification, compliance to compound matcher in salt
+ * @param extra_tgt Extra targets for compound
+ */
+def installRgw(master, target="I@ceph:radosgw", extra_tgt='') {
+ def salt = new Salt()
+
+ if(salt.testTarget(master, "I@ceph:radosgw $extra_tgt")) {
+ salt.fullRefresh(master, "I@ceph:radosgw $extra_tgt")
+ salt.enforceState([saltId: master, target: "I@ceph:radosgw $extra_tgt", state: ['keepalived', 'haproxy', 'ceph.radosgw']])
+ }
+}
+
+/**
+ * Remove rgw daemons from target
+ *
+ * @param master Salt connection object
+ * @param target Target specification, compliance to compound matcher in salt
+ * @param extra_tgt Extra targets for compound
+ */
+def removeRgw(master, target, extra_tgt='') {
+ def salt = new Salt()
+
+ // TODO needs to be reviewed
+ salt.fullRefresh(master, "I@ceph:radosgw $extra_tgt")
+ salt.enforceState([saltId: master, target: "I@ceph:radosgw $extra_tgt", state: ['keepalived', 'haproxy', 'ceph.radosgw']])
+}
+
+/**
+ * Remove osd daemons from target
+ *
+ * @param master Salt connection object
+ * @param target Target specification, compliance to compound matcher in salt
+ * @param osds List of osd to remove
+ * @param safeRemove Wait for data rebalance before remove drive
+ * @param target Target specification, compliance to compound matcher in salt
+ */
+def removeOsd(master, target, osds, flags, safeRemove=true, wipeDisks=false) {
+ def common = new Common()
+ def salt = new Salt()
+
+ // systemctl stop ceph-osd@0 && ceph osd purge 0 --yes-i-really-mean-it && umount /dev/vdc1; test -b /dev/vdc1 && dd if=/dev/zero of=/dev/vdc1 bs=1M; test -b /dev/vdc2 && dd if=/dev/zero of=/dev/vdc2 bs=1M count=100; sgdisk -d1 -d2 /dev/vdc; partprobe
+ if(osds.isEmpty()) {
+ common.warningMsg('List of OSDs was empty. No OSD is removed from cluster')
+ return
+ }
+
+ // `ceph osd out <id> <id>`
+ cmdRun(master, 'ceph osd out ' + osds.join(' '), true, true)
+
+ if(safeRemove) {
+ waitForHealthy(master, flags)
+ }
+
+ for(osd in osds) {
+ salt.runSaltProcessStep(master, target, 'service.stop', "ceph-osd@$osd", null, true)
+ cmdRun(master, "ceph osd purge $osd --yes-i-really-mean-it", true, true)
+ }
+
+ for(osd in osds) {
+ def lvm_enabled = getPillar(master, target, "ceph:osd:lvm_enabled")
+ if(lvm_enabled) {
+ // ceph-volume lvm zap --osd-id 1 --osd-fsid 55BD4219-16A7-4037-BC20-0F158EFCC83D --destroy
+ def output = cmdRunOnTarget(master, target, "ceph-volume lvm zap --osd-id $osd --destroy >/dev/null && echo 'zaped'", false)
+ if(output == 'zaped') { continue }
+ }
+
+ common.infoMsg("Removing legacy osd.")
+ def journal_partition = ""
+ def block_db_partition = ""
+ def block_wal_partition = ""
+ def block_partition = ""
+ def data_partition = ""
+ def dataDir = "/var/lib/ceph/osd/ceph-$osd"
+ journal_partition = cmdRunOnTarget(master, target,
+ "test -f $dataDir/journal_uuid && readlink -f /dev/disk/by-partuuid/`cat $dataDir/journal_uuid`", false)
+ block_db_partition = cmdRunOnTarget(master, target,
+ "test -f $dataDir/block.db_uuid && readlink -f /dev/disk/by-partuuid/`cat $dataDir/block.db_uuid`", false)
+ block_wal_partition = cmdRunOnTarget(master, target,
+ "test -f $dataDir/block.wal_uuid && readlink -f /dev/disk/by-partuuid/`cat $dataDir/block.wal_uuid`", false)
+ block_partition = cmdRunOnTarget(master, target,
+ "test -f $dataDir/block_uuid && readlink -f /dev/disk/by-partuuid/`cat $dataDir/block_uuid`", false)
+ data_partition = cmdRunOnTarget(master, target,
+ "test -f $dataDir/fsid && readlink -f /dev/disk/by-partuuid/`cat $dataDir/fsid`", false)
+
+ try {
+ if(journal_partition.trim()) { removePartition(master, target, journal_partition) }
+ if(block_db_partition.trim()) { removePartition(master, target, block_db_partition) }
+ if(block_wal_partition.trim()) { removePartition(master, target, block_wal_partition) }
+ if(block_partition.trim()) { removePartition(master, target, block_partition, 'block', wipeDisks) }
+ if(data_partition.trim()) { removePartition(master, target, data_partition, 'data', wipeDisks) }
+ else { common.warningMsg("Can't find data partition for osd.$osd") }
+ }
+ catch(Exception e) {
+ // report but continue as problem on one osd could be sorted out after
+ common.errorMsg("Found some issue during cleaning partition for osd.$osd on $target")
+ common.errorMsg(e)
+ currentBuild.result = 'FAILURE'
+ }
+
+ cmdRunOnTarget(master, target, "partprobe", false)
+ }
+}
+
+/**
+ * Update montoring for target hosts
+ *
+ * @param master Salt connection object
+ * @param target Target specification, compliance to compound matcher in salt
+ * @param extra_tgt Extra targets for compound
+ */
+def updateMonitoring(master, target="I@ceph:common", extra_tgt='') {
+ def common = new Common()
+ def salt = new Salt()
+
+ def prometheusNodes = salt.getMinions(master, "I@prometheus:server $extra_tgt")
+ if(!prometheusNodes.isEmpty()) {
+ //Collect Grains
+ salt.enforceState([saltId: master, target: "$target $extra_tgt", state: 'salt.minion.grains'])
+ salt.runSaltProcessStep(master, "$target $extra_tgt", 'saltutil.refresh_modules')
+ salt.runSaltProcessStep(master, "$target $extra_tgt", 'mine.update')
+ sleep(5)
+ salt.enforceState([saltId: master, target: "$target $extra_tgt", state: ['fluentd', 'telegraf', 'prometheus']])
+ salt.enforceState([saltId: master, target: "I@prometheus:server $extra_tgt", state: 'prometheus'])
+ }
+ else {
+ common.infoMsg('No Prometheus nodes in cluster. Nothing to do.')
+ }
+}
+
+def connectCeph(master, extra_tgt='') {
+ new Common().infoMsg("This method was renamed. Use method connectOS insead.")
+ connectOS(master, extra_tgt)
+}
+
+/**
+ * Enforce configuration and connect OpenStack clients
+ *
+ * @param master Salt connection object
+ * @param extra_tgt Extra targets for compound
+ */
+def connectOS(master, extra_tgt='') {
+ def salt = new Salt()
+
+ // setup Keystone service and endpoints for swift or / and S3
+ salt.enforceStateWithTest([saltId: master, target: "I@keystone:client $extra_tgt", state: 'keystone.client'])
+
+ // connect Ceph to the env
+ if(salt.testTarget(master, "I@ceph:common and I@glance:server $extra_tgt")) {
+ salt.enforceState([saltId: master, target: "I@ceph:common and I@glance:server $extra_tgt", state: ['glance']])
+ salt.runSaltProcessStep(master, "I@ceph:common and I@glance:server $extra_tgt", 'service.restart', ['glance-api'])
+ }
+ if(salt.testTarget(master, "I@ceph:common and I@cinder:controller $extra_tgt")) {
+ salt.enforceState([saltId: master, target: "I@ceph:common and I@cinder:controller $extra_tgt", state: ['cinder']])
+ salt.runSaltProcessStep(master, "I@ceph:common and I@cinder:controller $extra_tgt", 'service.restart', ['cinder-volume'])
+ }
+ if(salt.testTarget(master, "I@ceph:common and I@nova:compute $extra_tgt")) {
+ salt.enforceState([saltId: master, target: "I@ceph:common and I@nova:compute $extra_tgt", state: ['nova']])
+ salt.runSaltProcessStep(master, "I@ceph:common and I@nova:compute $extra_tgt", 'service.restart', ['nova-compute'])
+ }
+ if(salt.testTarget(master, "I@ceph:common and I@gnocchi:server $extra_tgt")) {
+ salt.enforceState([saltId: master, target: "I@ceph:common and I@gnocchi:server:role:primary $extra_tgt", state: 'gnocchi.server'])
+ salt.enforceState([saltId: master, target: "I@ceph:common and I@gnocchi:server $extra_tgt", state: 'gnocchi.server'])
+ }
+}
+
+/**
+ * Remove vm from VCP
+ *
+ * @param master Salt connection object
+ * @param target Target specification, compliance to compound matcher in salt
+ */
+def removeVm(master, target) {
+ def common = new Common()
+ def salt = new Salt()
+
+ def fqdn = getGrain(master, target, 'id')
+ def hostname = salt.stripDomainName(fqdn)
+ def hypervisor = getPillar(master, "I@salt:control", "salt:control:cluster:internal:node:$hostname:provider")
+
+ removeSalt(master, target)
+
+ if(hypervisor?.trim()) {
+ cmdRunOnTarget(master, hypervisor, "virsh destroy $fqdn")
+ cmdRunOnTarget(master, hypervisor, "virsh undefine $fqdn")
+ }
+ else {
+ common.errorMsg("There is no provider in pillar for $hostname")
+ }
+}
+
+/**
+ * Stop target salt minion, remove its key on master and definition in reclass
+ *
+ * @param master Salt connection object
+ * @param target Target specification, compliance to compound matcher in salt
+ */
+def removeSalt(master, target) {
+ def common = new Common()
+
+ def fqdn = getGrain(master, target, 'id')
+ try {
+ cmdRunOnTarget(master, 'I@salt:master', "salt-key --include-accepted -r $fqdn -y")
+ }
+ catch(Exception e) {
+ common.warningMsg(e)
+ }
+}
+
+def deleteKeyrings(master, target, extra_tgt='') {
+ def host = getGrain(master, target, 'host')
+ def keys = cmdRun(master, "ceph auth list 2>/dev/null | grep $host", false).tokenize('\n')
+ if(keys.isEmpty()) {
+ new Common().warningMsg("Nothing to do. There is no keyring for $host")
+ }
+ for(key in keys) {
+ cmdRun(master, "ceph auth del $key")
+ }
+}
+
+def generateMapping(pgmap,map) {
+ def pg_new
+ def pg_old
+ for(pg in pgmap) {
+ pg_new = pg["up"].minus(pg["acting"])
+ pg_old = pg["acting"].minus(pg["up"])
+ for(int i = 0; i < pg_new.size(); i++) {
+ // def string = "ceph osd pg-upmap-items " + pg["pgid"].toString() + " " + pg_new[i] + " " + pg_old[i] + ";"
+ def string = "ceph osd pg-upmap-items ${pg["pgid"]} ${pg_new[i]} ${pg_old[i]}"
+ map.add(string)
+ }
+ }
+}
+
+/**
+ * Run command on the first of avaliable ceph monitors
+ *
+ * @param master Salt connection object
+ * @param cmd Command to run
+ * @param checkResponse Check response of command. (optional, default true)
+ * @param output Print output (optional, default false)
+ */
+def cmdRun(master, cmd, checkResponse=true, output=false) {
+ def salt = new Salt()
+ def cmn01 = salt.getFirstMinion(master, "I@ceph:mon")
+ return salt.cmdRun(master, cmn01, cmd, checkResponse, null, output)['return'][0][cmn01]
+}
+
+/**
+ * Run command on target host
+ *
+ * @param master Salt connection object
+ * @param target Target specification, compliance to compound matcher in salt
+ * @param cmd Command to run
+ * @param checkResponse Check response of command. (optional, default true)
+ * @param output Print output (optional, default false)
+ */
+def cmdRunOnTarget(master, target, cmd, checkResponse=true, output=false) {
+ def salt = new Salt()
+ return salt.cmdRun(master, target, cmd, checkResponse, null, output)['return'][0].values()[0]
+}
+
+/**
+ * Ceph refresh pillars and get one for first host
+ *
+ * @param master Salt connection object
+ * @param target Target specification, compliance to compound matcher in salt
+ * @param pillar Pillar to obtain
+ */
+def getPillar(master, target, pillar) {
+ def common = new Common()
+ def salt = new Salt()
+ try {
+ return salt.getPillar(master, target, pillar)['return'][0].values()[0]
+ }
+ catch(Exception e) {
+ common.warningMsg('There was no pillar for the target.')
+ }
+}
+
+/**
+ * Ceph refresh grains and get one for first host
+ *
+ * @param master Salt connection object
+ * @param target Target specification, compliance to compound matcher in salt
+ * @param grain Grain to obtain
+ */
+def getGrain(master, target, grain) {
+ def common = new Common()
+ def salt = new Salt()
+ try {
+ return salt.getGrain(master, target, grain)['return'][0].values()[0].values()[0]
+ }
+ catch(Exception e) {
+ common.warningMsg('There was no grain for the target.')
+ }
+}
+
+/**
+ * Set flags
+ *
+ * @param master Salt connection object
+ * @param flags Collection of flags to set
+ */
+def setFlags(master, flags) {
+ if(flags instanceof String) { flags = [flags] }
+ for(flag in flags) {
+ cmdRun(master, 'ceph osd set ' + flag)
+ }
+}
+
+/**
+ * Unset flags
+ *
+ * @param master Salt connection object
+ * @param flags Collection of flags to unset (optional)
+ */
+def unsetFlags(master, flags=[]) {
+ if(flags instanceof String) { flags = [flags] }
+ for(flag in flags) {
+ cmdRun(master, 'ceph osd unset ' + flag)
+ }
+}
+
+/**
+ * Wait for healthy cluster while ignoring flags which have been set
+ *
+ * @param master Salt connection object
+ * @param attempts Attempts before it pause execution (optional, default 300)
+ */
+def waitForHealthy(master, flags, attempts=300) {
+ def common = new Common()
+
+ def count = 0
+ def isHealthy = false
+ def health = ''
+
+ // wait for current ops will be reflected in status
+ sleep(5)
+
+ while(count++ < attempts) {
+ health = cmdRun(master, 'ceph health', false)
+ if(health == 'HEALTH_OK') { return }
+ else {
+ // HEALTH_WARN noout,norebalance flag(s) set
+ def unexpectedFlags = health.tokenize(' ').getAt(1)?.tokenize(',')
+ unexpectedFlags.removeAll(flags)
+ if(health.contains('HEALTH_WARN') && unexpectedFlags.isEmpty()) { return }
+ }
+ common.warningMsg("Ceph cluster is still unhealthy: $health")
+ sleep(10)
+ }
+ // TODO: MissingMethodException
+ input message: "After ${count} attempts cluster is still unhealthy."
+ //throw new RuntimeException("After ${count} attempts cluster is still unhealthy. Can't proceed")
+}
+def waitForHealthy(master, String host, flags, attempts=300) {
+ new Common().warningMsg('This method will be deprecated.')
+ waitForHealthy(master, flags, attempts)
+}
+
+/**
+ * Remove unused orphan partition after some osds
+ *
+ * @param master Salt connection object
+ * @param target Target specification, compliance to compound matcher in salt
+ * @param wipePartitions Wipe each found partitions completely (optional, defaul false)
+ */
+def removeOrphans(master, target, wipePartitions=false) {
+ def common = new Common()
+ def salt = new Salt()
+
+ def orphans = []
+ // TODO: ceph-disk is avaliable only in luminous
+ def disks = cmdRunOnTarget(master, target, "ceph-disk list --format json 2>/dev/null",false)
+ disks = "{\"disks\":$disks}" // common.parseJSON() can't parse a list of maps
+ disks = common.parseJSON(disks)['disks']
+ for(disk in disks) {
+ for(partition in disk.get('partitions')) {
+ def orphan = false
+ if(partition.get('type') == 'block.db' && !partition.containsKey('block.db_for')) { orphan = true }
+ else if(partition.get('type') == 'block' && !partition.containsKey('block_for')) { orphan = true }
+ else if(partition.get('type') == 'data' && !partition.get('state') == 'active') { orphan = true }
+ // TODO: test for the rest of types
+
+ if(orphan) {
+ if(partition.get('path')) {
+ removePartition(master, target, partition['path'], partition['type'], wipePartitions)
+ }
+ else {
+ common.warningMsg("Found orphan partition on $target but failed to remove it.")
}
}
}
- common.infoMsg("Ceph health status: ${health}")
- count++
- sleep(10)
}
+ cmdRunOnTarget(master, target, "partprobe", false)
}
/**
* Ceph remove partition
*
+ * @param master Salt connection object
+ * @param target Target specification, compliance to compound matcher in salt
+ * @param partition Partition to remove on target host
+ * @param type Type of partition. Some partition need additional steps (optional, default empty string)
+ * @param fullWipe Fill the entire partition with zeros (optional, default false)
*/
-def removePartition(master, target, partition_uuid, type='', id=-1) {
- def salt = new com.mirantis.mk.Salt()
- def common = new com.mirantis.mk.Common()
- def partition = ''
+def removePartition(master, target, partition, type='', fullWipe=false) {
+ def common = new Common()
+ def salt = new Salt()
+
def dev = ''
def part_id = ''
- def lvm_enabled = salt.getPillar(master, "I@ceph:osd", "ceph:osd:lvm_enabled")['return'].first().containsValue(true)
- if ( !lvm_enabled ){
- if (type == 'lockbox') {
- try {
- // umount - partition = /dev/sdi2
- partition = salt.cmdRun(master, target, "lsblk -rp | grep -v mapper | grep ${partition_uuid} ")['return'][0].values()[0].split()[0]
- salt.cmdRun(master, target, "umount ${partition}")
- } catch (Exception e) {
- common.warningMsg(e)
- }
- } else if (type == 'data') {
- try {
- // umount - partition = /dev/sdi2
- partition = salt.cmdRun(master, target, "lsblk -rp | grep /var/lib/ceph/osd/ceph-${id}")['return'][0].values()[0].split()[0]
- salt.cmdRun(master, target, "umount ${partition}")
- } catch (Exception e) {
- common.warningMsg(e)
- }
- try {
- // partition = /dev/sdi2
- partition = salt.cmdRun(master, target, "blkid | grep ${partition_uuid} ")['return'][0].values()[0].split(":")[0]
- } catch (Exception e) {
- common.warningMsg(e)
- }
- } else {
- try {
- // partition = /dev/sdi2
- partition = salt.cmdRun(master, target, "blkid | grep ${partition_uuid} ")['return'][0].values()[0].split(":")[0]
- } catch (Exception e) {
- common.warningMsg(e)
- }
- }
- if (partition?.trim()) {
- if (partition.contains("nvme")) {
- // partition = /dev/nvme1n1p2
- // dev = /dev/nvme1n1
- dev = partition.replaceAll('p\\d+$', "")
- // part_id = 2
- part_id = partition.substring(partition.lastIndexOf("p") + 1).replaceAll("[^0-9]+", "")
+ def partitionID = ''
+ def disk = ''
+ def wipeCmd = ''
+ def lvm_enabled = getPillar(master, target, "ceph:osd:lvm_enabled")
- } else {
- // partition = /dev/sdi2
- // dev = /dev/sdi
- dev = partition.replaceAll('\\d+$', "")
- // part_id = 2
- part_id = partition.substring(partition.lastIndexOf("/") + 1).replaceAll("[^0-9]+", "")
- }
+ if(!partition?.trim()) {
+ throw new Exception("Can't proceed without defined partition.")
+ }
+ cmdRunOnTarget(master, target, "test -b $partition")
+
+ if(fullWipe) { wipeCmd = "dd if=/dev/zero of=$partition bs=1M 2>/dev/null" }
+ else { wipeCmd = "dd if=/dev/zero of=$partition bs=1M count=100 2>/dev/null" }
+
+ common.infoMsg("Removing from the cluster $type partition $partition on $target.")
+ if(type == 'lockbox') {
+ try {
+ partition = cmdRunOnTarget(master, target, "lsblk -rp | grep -v mapper | grep $partition", false)
+ cmdRunOnTarget(master, target, "umount $partition")
+ }
+ catch (Exception e) {
+ common.warningMsg(e)
}
}
- if (lvm_enabled && type != 'lockbox') {
- salt.cmdRun(master, target, "ceph-volume lvm zap /dev/disk/by-partuuid/${partition_uuid} --destroy")
- } else if (dev != '') {
- salt.cmdRun(master, target, "parted ${dev} rm ${part_id}")
- } else {
- common.infoMsg("Did not found any device to be wiped.")
+ else if(type == 'data') {
+ cmdRunOnTarget(master, target, "umount $partition 2>/dev/null", false)
+ cmdRunOnTarget(master, target, wipeCmd, false)
}
- return
+ else if(type == 'block' || fullWipe) {
+ cmdRunOnTarget(master, target, wipeCmd, false)
+ }
+ try {
+ partitionID = cmdRunOnTarget(master, target, "cat /sys/dev/block/`lsblk $partition -no MAJ:MIN | xargs`/partition", false)
+ disk = cmdRunOnTarget(master, target, "lsblk $partition -no pkname", false)
+ }
+ catch (Exception e) {
+ common.errorMsg("Couldn't get disk name or partition number for $partition")
+ common.warningMsg(e)
+ }
+ try {
+ cmdRunOnTarget(master, target, "sgdisk -d$partitionID /dev/$disk", true, true)
+ }
+ catch (Exception e) {
+ common.warningMsg("Did not found any device to be wiped.")
+ common.warningMsg(e)
+ }
+ // try to remove partition table if disk have no partitions left - required by ceph-volume
+ cmdRunOnTarget(master, target, "partprobe -d -s /dev/$disk | grep partitions\$ && sgdisk -Z /dev/$disk", false, true)
}
diff --git a/src/com/mirantis/mk/Orchestrate.groovy b/src/com/mirantis/mk/Orchestrate.groovy
index 70535ef..4827b8d 100644
--- a/src/com/mirantis/mk/Orchestrate.groovy
+++ b/src/com/mirantis/mk/Orchestrate.groovy
@@ -1175,90 +1175,23 @@
//
def installCephMon(master, target="I@ceph:mon", extra_tgt = '') {
- def salt = new com.mirantis.mk.Salt()
-
- salt.enforceState([saltId: master, target: "I@ceph:common ${extra_tgt}", state: 'salt.minion.grains'])
-
- // generate keyrings
- if (salt.testTarget(master, "( I@ceph:mon:keyring:mon or I@ceph:common:keyring:admin ) ${extra_tgt}")) {
- salt.enforceState([saltId: master, target: "( I@ceph:mon:keyring:mon or I@ceph:common:keyring:admin ) ${extra_tgt}", state: 'ceph.mon'])
- salt.runSaltProcessStep(master, "I@ceph:mon ${extra_tgt}", 'saltutil.sync_grains')
- salt.runSaltProcessStep(master, "( I@ceph:mon:keyring:mon or I@ceph:common:keyring:admin ) ${extra_tgt}", 'mine.update')
-
- // on target nodes mine is used to get pillar from 'ceph:common:keyring:admin' via grain.items
- // we need to refresh all pillar/grains to make data sharing work correctly
- salt.fullRefresh(master, "( I@ceph:mon:keyring:mon or I@ceph:common:keyring:admin ) ${extra_tgt}")
-
- sleep(5)
- }
- // install Ceph Mons
- salt.enforceState([saltId: master, target: target, state: 'ceph.mon'])
- salt.enforceStateWithTest([saltId: master, target: "I@ceph:mgr ${extra_tgt}", state: 'ceph.mgr'])
+ def ceph = new com.mirantis.mk.Ceph()
+ ceph.installMon(master, target, extra_tgt)
}
def installCephOsd(master, target="I@ceph:osd", setup=true, extra_tgt = '') {
- def salt = new com.mirantis.mk.Salt()
-
- // install Ceph OSDs
- salt.enforceState([saltId: master, target: target, state: 'ceph.osd'])
- salt.runSaltProcessStep(master, "I@ceph:osd ${extra_tgt}", 'saltutil.sync_grains')
- salt.enforceState([saltId: master, target: target, state: 'ceph.osd.custom'])
- salt.runSaltProcessStep(master, "I@ceph:osd ${extra_tgt}", 'saltutil.sync_grains')
- salt.runSaltProcessStep(master, "I@ceph:osd ${extra_tgt}", 'mine.update')
- installBackup(master, 'ceph')
-
- // setup pools, keyrings and maybe crush
- if (salt.testTarget(master, "I@ceph:setup ${extra_tgt}") && setup) {
- sleep(5)
- salt.enforceState([saltId: master, target: "I@ceph:setup ${extra_tgt}", state: 'ceph.setup'])
- }
+ def ceph = new com.mirantis.mk.Ceph()
+ ceph.installOsd(master, target, setup, extra_tgt)
}
def installCephClient(master, extra_tgt = '') {
- def salt = new com.mirantis.mk.Salt()
-
- // install Ceph Radosgw
- if (salt.testTarget(master, "I@ceph:radosgw ${extra_tgt}")) {
- salt.runSaltProcessStep(master, "I@ceph:radosgw ${extra_tgt}", 'saltutil.sync_grains')
- salt.enforceState([saltId: master, target: "I@ceph:radosgw ${extra_tgt}", state: 'ceph.radosgw'])
- }
-
- // setup keyring for Openstack services
- salt.enforceStateWithTest([saltId: master, target: "I@ceph:common and I@glance:server ${extra_tgt}", state: ['ceph.common', 'ceph.setup.keyring']])
-
- salt.enforceStateWithTest([saltId: master, target: "I@ceph:common and I@cinder:controller ${extra_tgt}", state: ['ceph.common', 'ceph.setup.keyring']])
-
- if (salt.testTarget(master, "I@ceph:common and I@nova:compute ${extra_tgt}")) {
- salt.enforceState([saltId: master, target: "I@ceph:common and I@nova:compute ${extra_tgt}", state: ['ceph.common', 'ceph.setup.keyring']])
- salt.runSaltProcessStep(master, "I@ceph:common and I@nova:compute ${extra_tgt}", 'saltutil.sync_grains')
- }
-
- salt.enforceStateWithTest([saltId: master, target: "I@ceph:common and I@gnocchi:server ${extra_tgt}", state: ['ceph.common', 'ceph.setup.keyring']])
+ def ceph = new com.mirantis.mk.Ceph()
+ ceph.installClient(master, extra_tgt)
}
def connectCeph(master, extra_tgt = '') {
- def salt = new com.mirantis.mk.Salt()
-
- // setup Keystone service and endpoints for swift or / and S3
- salt.enforceStateWithTest([saltId: master, target: "I@keystone:client ${extra_tgt}", state: 'keystone.client'])
-
- // connect Ceph to the env
- if (salt.testTarget(master, "I@ceph:common and I@glance:server ${extra_tgt}")) {
- salt.enforceState([saltId: master, target: "I@ceph:common and I@glance:server ${extra_tgt}", state: ['glance']])
- salt.runSaltProcessStep(master, "I@ceph:common and I@glance:server ${extra_tgt}", 'service.restart', ['glance-api'])
- }
- if (salt.testTarget(master, "I@ceph:common and I@cinder:controller ${extra_tgt}")) {
- salt.enforceState([saltId: master, target: "I@ceph:common and I@cinder:controller ${extra_tgt}", state: ['cinder']])
- salt.runSaltProcessStep(master, "I@ceph:common and I@cinder:controller ${extra_tgt}", 'service.restart', ['cinder-volume'])
- }
- if (salt.testTarget(master, "I@ceph:common and I@nova:compute ${extra_tgt}")) {
- salt.enforceState([saltId: master, target: "I@ceph:common and I@nova:compute ${extra_tgt}", state: ['nova']])
- salt.runSaltProcessStep(master, "I@ceph:common and I@nova:compute ${extra_tgt}", 'service.restart', ['nova-compute'])
- }
- if (salt.testTarget(master, "I@ceph:common and I@gnocchi:server ${extra_tgt}")) {
- salt.enforceState([saltId: master, target: "I@ceph:common and I@gnocchi:server:role:primary ${extra_tgt}", state: 'gnocchi.server'])
- salt.enforceState([saltId: master, target: "I@ceph:common and I@gnocchi:server ${extra_tgt}", state: 'gnocchi.server'])
- }
+ def ceph = new com.mirantis.mk.Ceph()
+ ceph.connectOS(master, extra_tgt)
}
def installOssInfra(master, extra_tgt = '') {