Skip to content

Commit

Permalink
LXD and KVM plugin to be able to use already defined images (#60)
Browse files Browse the repository at this point in the history
# Bugfix
- LXD and KVM plugin where unable to define FDUs where the image is passed as reference, this has ben solved by this PR.
  • Loading branch information
gabrik committed Apr 9, 2019
1 parent 7cb83ec commit 5bcb3ce
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 91 deletions.
59 changes: 29 additions & 30 deletions fos-plugins/KVM/KVM_plugin
Original file line number Diff line number Diff line change
Expand Up @@ -148,41 +148,40 @@ class KVM(RuntimePluginFDU):
fdu = KVMFDU.from_descriptor(descriptor)

if self.is_uuid(fdu.get_image_uri()):
img = self.images.get(fdu.get_image_uri(), None)
img = self.get_image_info(fdu.get_image_uri())
self.logger.info('define_fdu()', '[ INFO ] LXD Plugin - Img info: {}'.format(img))
if img is None:
self.logger.error('define_fdu()', '[ ERRO ] KVM Plugin - Cannot find image {}'.format(fdu.get_image_uri()))
# TODO write error using Yaks_connector
return
else:
fdu.image.update({'file':img.get('base_image')})
fdu.image.update({'uuid':img.get('uuid')})
fdu.image.update({'uri':img.get('uri')})
fdu.image.update({'uuid':img.get('uuid')})

else:
self.logger.warning('define_fdu()', '[ WARN ] KVM Plugin - No image id specified defining from manifest information new image id uuid:{}'.format(fdu_uuid))
if fdu.get_image_uri().startswith('http'):
image_name = os.path.join(self.BASE_DIR, self.IMAGE_DIR, fdu.get_image_uri().split('/')[-1])
self.call_os_plugin_function('download_file',{'url':fdu.get_image_uri(),'file_path':image_name})
elif fdu.get_image_uri().startswith('file://'):
image_name = os.path.join(
self.BASE_DIR, self.IMAGE_DIR, fdu.get_image_uri().split('/')[-1])
cmd = 'cp {} {}'.format(fdu.get_image_uri()[len('file://'):], image_name)
self.call_os_plugin_function('execute_command',{'command':cmd,'blocking':True, 'external':False})


img_info = {}
img_info.update({'uuid': fdu_uuid})
img_info.update({'name': '{}_img'.format(fdu.name)})
img_info.update({'base_image': image_name})
img_info.update({'type':'kvm'})
img_info.update({'format': fdu.get_image_format()})

fdu.image.update({'file': image_name})
fdu.image.update({'uuid': fdu_uuid})

self.__add_image(img_info)
img = self.images.get(fdu_uuid, None)
if img is None:
self.logger.error('define_fdu()', '[ ERRO ] KVM Plugin - Cannot find image {}'.format(fdu_uuid))
#self.logger.warning('define_fdu()', '[ WARN ] KVM Plugin - No image id specified defining from manifest information new image id uuid:{}'.format(fdu_uuid))
if fdu.get_image_uri().startswith('http'):
image_name = os.path.join(self.BASE_DIR, self.IMAGE_DIR, fdu.get_image_uri().split('/')[-1])
self.call_os_plugin_function('download_file',{'url':fdu.get_image_uri(),'file_path':image_name})
elif fdu.get_image_uri().startswith('file://'):
image_name = os.path.join(
self.BASE_DIR, self.IMAGE_DIR, fdu.get_image_uri().split('/')[-1])
cmd = 'cp {} {}'.format(fdu.get_image_uri()[len('file://'):], image_name)
self.call_os_plugin_function('execute_command',{'command':cmd,'blocking':True, 'external':False})


img_info = {}
img_info.update({'uuid': fdu_uuid})
img_info.update({'name': '{}_img'.format(fdu.name)})
img_info.update({'base_image': image_name})
img_info.update({'type':'kvm'})
img_info.update({'format': fdu.get_image_format()})

fdu.image.update({'file': image_name})
fdu.image.update({'uuid': fdu_uuid})

self.__add_image(img_info)
img = self.images.get(fdu_uuid, None)
if img is None:
self.logger.error('define_fdu()', '[ ERRO ] KVM Plugin - Cannot find image {}'.format(fdu_uuid))

self.logger.info('define_fdu()', '[ WARN ] KVM Plugin - New flavor uuid:{}'.format(fdu_uuid))
cpu = fdu.comp_requirements.get('cpu_min_count')
Expand Down
122 changes: 62 additions & 60 deletions fos-plugins/LXD/LXD_plugin
Original file line number Diff line number Diff line change
Expand Up @@ -160,78 +160,80 @@ class LXD(RuntimePluginFDU):
fdu = LXDFDU.from_descriptor(descriptor)

if self.is_uuid(fdu.get_image_uri()):
img_info = self.images.get(fdu.get_image_uri(), None)
img_info = self.get_image_info(fdu.get_image_uri())
self.logger.info('define_fdu()', '[ INFO ] LXD Plugin - Img info: {}'.format(img_info))
# img_info = self.images.get(fdu.get_image_uri(), None)
if img_info is None:
self.logger.error(
'define_fdu()', '[ ERRO ] LXD Plugin - Cannot find image {}'.format(fdu.get_image_uri()))
return
# self.__write_error_entity(fdu_uuid, 'Image not found!')

fdu.image.update({'file':img_info.get('base_image')})
fdu.image.update({'uri':img_info.get('uri')})
fdu.image.update({'uuid':img_info.get('uuid')})

else:
image_name = os.path.join(self.BASE_DIR, self.IMAGE_DIR, fdu.get_image_uri().split('/')[-1])
image_name = os.path.join(self.BASE_DIR, self.IMAGE_DIR, fdu.get_image_uri().split('/')[-1])

if not self.call_os_plugin_function('file_exists',{'file_path':image_name}):
if fdu.get_image_uri().startswith('http'):
self.call_os_plugin_function('download_file',{'url':fdu.get_image_uri(),'file_path':image_name})
elif fdu.get_image_uri().startswith('file://'):
cmd = 'cp {} {}'.format(fdu.get_image_uri()[len('file://'):], image_name)
self.call_os_plugin_function('execute_command',{'command':cmd,'blocking':True, 'external':False})

# TODO verify IMAGE CHECKSUM
img_info = {}
try:
# TODO: this should some how pass through YAKS, at this time the LXD plugin will read
# the file from the disk
# self.call_os_plugin_function('execute_command',{'file_path':os.path.join(self.BASE_DIR, self.IMAGE_DIR, image_name)})

# check first if image is already in LXD if not we add it, if yes, we use the image for the container
img_sum = self.call_os_plugin_function('checksum',{'file_path':image_name})
if self.conn.images.exists(img_sum):
self.logger.info('define_fdu()', '[ INFO ] LXD Plugin - Image with this fingerprint already exists, attaching it to container')
img = self.conn.images.get(img_sum)
img_uuid = img.aliases[0].get('name')
img_info.update({'uuid': img_uuid})
img_info.update({'name': '{}_img'.format(fdu.name)})
img_info.update({'base_image': image_name})
img_info.update({'type': 'lxd'})
img_info.update({'format': fdu.get_image_format()})
else:
self.logger.info('define_fdu()', '[ INFO ] LXD Plugin - Loading image data from: {}'.format(os.path.join(self.BASE_DIR, self.IMAGE_DIR, image_name)))
image_data = self.read_binary_file(os.path.join(self.BASE_DIR, self.IMAGE_DIR, image_name))
self.logger.info('define_fdu()', '[ DONE ] LXD Plugin - Loaded image data from: {}'.format(os.path.join(self.BASE_DIR, self.IMAGE_DIR, image_name)))

if not self.call_os_plugin_function('file_exists',{'file_path':image_name}):
if fdu.get_image_uri().startswith('http'):
self.call_os_plugin_function('download_file',{'url':fdu.get_image_uri(),'file_path':image_name})
elif fdu.get_image_uri().startswith('file://'):
cmd = 'cp {} {}'.format(fdu.get_image_uri()[len('file://'):], image_name)
self.call_os_plugin_function('execute_command',{'command':cmd,'blocking':True, 'external':False})
self.logger.info('define_fdu()', '[ INFO ] LXD Plugin - Creating image with alias {}'.format(fdu_uuid))
try:
img = self.conn.images.create(image_data, public=True, wait=True)
img.add_alias(fdu_uuid, description=fdu.name)
except LXDAPIException as e:
# TODO: check this error with errno
if '{}'.format(e) == 'Image with same fingerprint already exists':
self.logger.info('define_fdu()', '[ INFO ] LXD Plugin - Image with same fingerprint already exists')
pass
self.logger.info('define_fdu()', '[ DONE ] LXD Plugin - Created image with alias {}'.format(fdu_uuid))
img_info.update({'uuid': fdu_uuid})
img_info.update({'name': '{}_img'.format(fdu.name)})
img_info.update({'base_image': image_name})
img_info.update({'type': 'lxd'})
img_info.update({'format': fdu.get_image_format()})
self.images.update({fdu_uuid: img_info})
self.connector.loc.actual.add_node_image(self.node, self.uuid, fdu_uuid, img_info)

# TODO verify IMAGE CHECKSUM
img_info = {}
try:
# TODO: this should some how pass through YAKS, at this time the LXD plugin will read
# the file from the disk
# self.call_os_plugin_function('execute_command',{'file_path':os.path.join(self.BASE_DIR, self.IMAGE_DIR, image_name)})

# check first if image is already in LXD if not we add it, if yes, we use the image for the container
img_sum = self.call_os_plugin_function('checksum',{'file_path':image_name})
if self.conn.images.exists(img_sum):
self.logger.info('define_fdu()', '[ INFO ] LXD Plugin - Image with this fingerprint already exists, attaching it to container')
img = self.conn.images.get(img_sum)
img_uuid = img.aliases[0].get('name')
img_info.update({'uuid': img_uuid})
img_info.update({'name': '{}_img'.format(fdu.name)})
img_info.update({'base_image': image_name})
img_info.update({'type': 'lxd'})
img_info.update({'format': fdu.get_image_format()})
else:
self.logger.info('define_fdu()', '[ INFO ] LXD Plugin - Loading image data from: {}'.format(os.path.join(self.BASE_DIR, self.IMAGE_DIR, image_name)))
image_data = self.read_binary_file(os.path.join(self.BASE_DIR, self.IMAGE_DIR, image_name))
self.logger.info('define_fdu()', '[ DONE ] LXD Plugin - Loaded image data from: {}'.format(os.path.join(self.BASE_DIR, self.IMAGE_DIR, image_name)))

self.logger.info('define_fdu()', '[ INFO ] LXD Plugin - Creating image with alias {}'.format(fdu_uuid))
try:
img = self.conn.images.create(image_data, public=True, wait=True)
img.add_alias(fdu_uuid, description=fdu.name)
except LXDAPIException as e:
# TODO: check this error with errno
if '{}'.format(e) == 'Image with same fingerprint already exists':
self.logger.info('define_fdu()', '[ INFO ] LXD Plugin - Image with same fingerprint already exists')
pass
self.logger.info('define_fdu()', '[ DONE ] LXD Plugin - Created image with alias {}'.format(fdu_uuid))
img_info.update({'uuid': fdu_uuid})
img_info.update({'name': '{}_img'.format(fdu.name)})
img_info.update({'base_image': image_name})
img_info.update({'type': 'lxd'})
img_info.update({'format': fdu.get_image_format()})
self.images.update({fdu_uuid: img_info})
self.connector.loc.actual.add_node_image(self.node, self.uuid, fdu_uuid, img_info)

fdu.image.update({'file': image_name})
fdu.image.update({'uuid': img_info.get('uuid')})
fdu.image.update({'file': image_name})
fdu.image.update({'uuid': img_info.get('uuid')})



except LXDAPIException as e:
self.logger.error('define_fdu()', 'Error {}'.format(e))
self.current_fdus.update({fdu_uuid: fdu})
lxd_info = self.connector.loc.desired.get_node_fdu(self.node, self.uuid, fdu_uuid)
lxd_info.update({'status': 'ERROR'})
self.connector.loc.actual.add_node_fdu(self.node, self.uuid, fdu_uuid, lxd_info)
self.logger.info('define_fdu()', '[ ERRO ] LXD Plugin - Container uuid: {}'.format(fdu_uuid))
except LXDAPIException as e:
self.logger.error('define_fdu()', 'Error {}'.format(e))
self.current_fdus.update({fdu_uuid: fdu})
lxd_info = self.connector.loc.desired.get_node_fdu(self.node, self.uuid, fdu_uuid)
lxd_info.update({'status': 'ERROR'})
self.connector.loc.actual.add_node_fdu(self.node, self.uuid, fdu_uuid, lxd_info)
self.logger.info('define_fdu()', '[ ERRO ] LXD Plugin - Container uuid: {}'.format(fdu_uuid))



Expand Down
13 changes: 13 additions & 0 deletions src/agent/fos-agent/fos_agent.ml
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,18 @@ let agent verbose_flag debug_flag configuration =
| _ -> let eval_res = FAgentTypes.{result = None ; error=Some 11} in
Lwt.return @@ FAgentTypes.string_of_eval_result eval_res
in
let eval_get_image_info self (props:Apero.properties) =
MVar.read self >>= fun state ->
let image_uuid = Apero.Option.get @@ Apero.Properties.get "image_uuid" props in
try%lwt
let%lwt descriptor = Yaks_connector.Global.Actual.get_image sys_id Yaks_connector.default_tenant_id image_uuid state.yaks in
let js = FAgentTypes.json_of_string @@ FTypes.string_of_image descriptor in
let eval_res = FAgentTypes.{result = Some js ; error=None} in
Lwt.return @@ FAgentTypes.string_of_eval_result eval_res
with
| _ -> let eval_res = FAgentTypes.{result = None ; error=Some 11} in
Lwt.return @@ FAgentTypes.string_of_eval_result eval_res
in
let eval_get_node_fdu_info self (props:Apero.properties) =
MVar.read self >>= fun state ->
let fdu_uuid = Apero.Option.get @@ Apero.Properties.get "fdu_uuid" props in
Expand Down Expand Up @@ -629,6 +641,7 @@ let agent verbose_flag debug_flag configuration =
let%lwt _ = Yaks_connector.Local.Actual.add_agent_eval uuid "get_node_mgmt_address" (eval_get_node_mgmt_address state) yaks in
let%lwt _ = Yaks_connector.Local.Actual.add_agent_eval uuid "get_network_info" (eval_get_network_info state) yaks in
let%lwt _ = Yaks_connector.Local.Actual.add_agent_eval uuid "get_port_info" (eval_get_port_info state) yaks in
let%lwt _ = Yaks_connector.Local.Actual.add_agent_eval uuid "get_image_info" (eval_get_image_info state) yaks in
(* Constraint Eval *)
let%lwt _ = Yaks_connector.LocalConstraint.Actual.add_agent_eval uuid "get_fdu_info" (eval_get_fdu_info state) yaks in
(* Registering listeners *)
Expand Down
10 changes: 9 additions & 1 deletion src/api/python/api/fog05/interfaces/RuntimePluginFDU.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,15 @@ def get_destination_node_mgmt_net(self, destinationid):
parameters = {
'node_uuid': destinationid
}
fname = 'get_node_mgmt_address'
fname = 'get_image_info'
return self.call_agent_function(fname, parameters)


def get_image_info(self, imageid):
parameters = {
'image_uuid': imageid
}
fname = 'get_image_info'
return self.call_agent_function(fname, parameters)


Expand Down

0 comments on commit 5bcb3ce

Please sign in to comment.