2
0
mirror of https://github.com/xcat2/confluent.git synced 2025-04-10 09:45:16 +00:00

Implement a number of OS deployment management enhancements.

Add capability to fingerprint media without doing a full import (/deployment/fingerprinting/)

Add fetching the profile info as json under the /deployment/ api.

Prepare to support custom distribution name on import
This commit is contained in:
Jarrod Johnson 2024-01-22 17:22:47 -05:00
parent 07a7357c87
commit b90718982e
3 changed files with 56 additions and 17 deletions

View File

@ -70,6 +70,7 @@ import os
import eventlet.green.socket as socket
import struct
import sys
import yaml
pluginmap = {}
dispatch_plugins = (b'ipmi', u'ipmi', b'redfish', u'redfish', b'tsmsol', u'tsmsol', b'geist', u'geist', b'deltapdu', u'deltapdu', b'eatonpdu', u'eatonpdu', b'affluent', u'affluent', b'cnos', u'cnos')
@ -177,6 +178,7 @@ def handle_storage(configmanager, inputdata, pathcomponents, operation):
if pathcomponents[1] == 'remote':
for rsp in mountmanager.handle_request(configmanager, inputdata, pathcomponents[2:], operation):
yield rsp
def handle_deployment(configmanager, inputdata, pathcomponents,
operation):
if len(pathcomponents) == 1:
@ -199,8 +201,19 @@ def handle_deployment(configmanager, inputdata, pathcomponents,
for prof in osimage.list_profiles():
yield msg.ChildCollection(prof + '/')
return
if len(pathcomponents) == 3:
profname = pathcomponents[-1]
if len(pathcomponents) >= 3:
profname = pathcomponents[2]
if len(pathcomponents) == 4:
if operation == 'retrieve':
if len(pathcomponents) == 4 and pathcomponents[-1] == 'info':
with open('/var/lib/confluent/public/os/{}/profile.yaml'.format(profname)) as profyaml:
profinfo = yaml.safe_load(profyaml)
profinfo['name'] = profname
yield msg.KeyValueData(profinfo)
return
elif len(pathcomponents) == 3:
if operation == 'retrieve':
yield msg.ChildCollection('info')
if operation == 'update':
if 'updateboot' in inputdata:
osimage.update_boot(profname)
@ -216,6 +229,17 @@ def handle_deployment(configmanager, inputdata, pathcomponents,
for cust in customized:
yield msg.KeyValueData({'customized': cust})
return
if pathcomponents[1] == 'fingerprint':
if operation == 'create':
importer = osimage.MediaImporter(inputdata['filename'], configmanager, checkonly=True)
medinfo = {
'targetpath': importer.targpath,
'name': importer.osname,
'oscategory': importer.oscategory,
'errors': importer.errors,
}
yield msg.KeyValueData(medinfo)
return
if pathcomponents[1] == 'importing':
if len(pathcomponents) == 2 or not pathcomponents[-1]:
if operation == 'retrieve':
@ -223,8 +247,12 @@ def handle_deployment(configmanager, inputdata, pathcomponents,
yield imp
return
elif operation == 'create':
importer = osimage.MediaImporter(inputdata['filename'],
configmanager)
if inputdata.get('custname', None):
importer = osimage.MediaImporter(inputdata['filename'],
configmanager, inputdata['custname'])
else:
importer = osimage.MediaImporter(inputdata['filename'],
configmanager)
yield msg.KeyValueData({'target': importer.targpath,
'name': importer.importkey})
return

View File

@ -28,6 +28,7 @@ def handle_request(configmanager, inputdata, pathcomponents, operation):
mountsbyuser[curruser].append(currmount)
yield msg.KeyValueData({
'path': currmount['path'],
'fullpath': '/var/run/confluent/browserfs/mount/{}'.format(currmount['path']),
'authtoken': currmount['authtoken']
})

View File

@ -747,9 +747,9 @@ def rebase_profile(dirname):
# customization detected, skip
# else
# update required, manifest update
def get_hashes(dirname):
hashmap = {}
for dname, _, fnames in os.walk(dirname):
@ -776,7 +776,7 @@ def generate_stock_profiles(defprofile, distpath, targpath, osname,
continue
oumask = os.umask(0o22)
shutil.copytree(srcname, dirname)
hmap = get_hashes(dirname)
hmap = get_hashes(dirname)
profdata = None
try:
os.makedirs('{0}/boot/initramfs'.format(dirname), 0o755)
@ -824,11 +824,12 @@ def generate_stock_profiles(defprofile, distpath, targpath, osname,
class MediaImporter(object):
def __init__(self, media, cfm=None):
def __init__(self, media, cfm=None, customname=None, checkonly=False):
self.worker = None
if not os.path.exists('/var/lib/confluent/public'):
raise Exception('`osdeploy initialize` must be executed before importing any media')
self.profiles = []
self.errors = []
medfile = None
self.medfile = None
if cfm and media in cfm.clientfiles:
@ -848,25 +849,34 @@ class MediaImporter(object):
self.phase = 'copying'
if not identity:
raise Exception('Unrecognized OS Media')
if 'subname' in identity:
if customname:
importkey = customname
elif 'subname' in identity:
importkey = '{0}-{1}'.format(identity['name'], identity['subname'])
else:
importkey = identity['name']
if importkey in importing:
if importkey in importing and not checkonly:
raise Exception('Media import already in progress for this media')
self.importkey = importkey
importing[importkey] = self
self.importkey = importkey
self.osname = identity['name']
self.oscategory = identity.get('category', None)
targpath = identity['name']
if customname:
targpath = customname
else:
targpath = identity['name']
self.distpath = '/var/lib/confluent/distributions/' + targpath
if identity.get('subname', None):
if identity.get('subname', None): # subname is to indicate disk number in a media set
targpath += '/' + identity['subname']
self.targpath = '/var/lib/confluent/distributions/' + targpath
if os.path.exists(self.targpath):
del importing[importkey]
raise Exception('{0} already exists'.format(self.targpath))
errstr = '{0} already exists'.format(self.targpath)
if checkonly:
self.errors = [errstr]
else:
raise Exception(errstr)
if checkonly:
return
importing[importkey] = self
self.filename = os.path.abspath(media)
self.error = ''
self.importer = eventlet.spawn(self.importmedia)