Added downloading bitstream when programming fpga

How to test the flow of program process manually:
1. generate the fake env by the follow command
cat > ./fake_env.sh << EOL
SYSINFO=cyborg/accelerator/drivers/fpga/intel/sysinfo.py
UTILS=cyborg/accelerator/drivers/fpga/utils.py
sed -i -e 's/^\(SYS_FPGA\) = "\(\/sys\/class\/fpga\)"$/\1 = "\/tmp\2"/g' $SYSINFO
sed -i -e 's/^\(SYS_FPGA_PATH\) = "\(\/sys\/class\/fpga\)"$/\1 = "\/tmp\2"/g' $UTILS
python cyborg/tests/unit/accelerator/drivers/fpga/intel/prepare_test_data.py
LOG=/tmp/intel_fpga_program.log
sudo echo 'echo fpgaconf \$@ '"|tee $LOG" > /usr/bin/fpgaconf
sudo echo "date |tee -a $LOG" >> /usr/bin/fpgaconf
sudo echo "echo 'Program intel FPGA successfully' |tee -a $LOG" >> /usr/bin/fpgaconf
sudo chmod a+x /usr/bin/fpgaconf
EOL

chmod a+x ./fake_env.sh
sudo ./fake_env.sh

2. Please use curl command as follows:
curl -s -X PATCH -H "X-Auth-Token: $OS_TOKEN" -H "Content-Type: application/json"\
  -d '[{
    	"path": "/program",
    	"op": "replace",
    	"value": [{
    		"image_uuid": "{image_uuid}"
    	}]
  }]'\
  http://{host_ip}:6666/v1/accelerators/deployables/{deployable_uuid}/program

3. Checke the /tmp/intel_fpga_program.log it should see the infomation as
the follow exmaple:
$ cat /tmp/intel_fpga_program.log
fpgaconf -b 04 -d 00 -f 1 4047d422-5d2f-432c-b87f-5e1749e95ee6.bin
Sat Oct 27 15:08:34 UTC 2018
Program intel FPGA successfully

Change-Id: I70ff5edac65fe9e9ec1783d62c2ecd21ac5fab18
This commit is contained in:
Li Liu 2018-10-17 23:30:44 -04:00 committed by Shaohe Feng
parent 156c9f18e5
commit 0bd8a7d9de
8 changed files with 54 additions and 7 deletions

View File

@ -46,7 +46,7 @@ class IntelFPGADriver(FPGADriver):
else:
bdf = sysinfo.get_bdf_by_path(path)
bdfs = sysinfo.split_bdf(bdf)
cmd = ["sudo", "fpgaconf"]
cmd = ["sudo", "/usr/bin/fpgaconf"]
for i in zip(["-b", "-d", "-f"], bdfs):
cmd.extend(i)
cmd.append(image)

View File

@ -18,6 +18,8 @@ from oslo_service import periodic_task
from cyborg.accelerator.drivers.fpga.base import FPGADriver
from cyborg.agent.resource_tracker import ResourceTracker
from cyborg.agent.rpcapi import AgentAPI
from cyborg.image.api import API as ImageAPI
from cyborg.conductor import rpcapi as cond_api
from cyborg.conf import CONF
@ -34,6 +36,8 @@ class AgentManager(periodic_task.PeriodicTasks):
self.host = host or CONF.host
self.fpga_driver = FPGADriver()
self.cond_api = cond_api.ConductorAPI()
self.agent_api = AgentAPI()
self.image_api = ImageAPI()
self._rt = ResourceTracker(host, self.cond_api)
def periodic_tasks(self, context, raise_on_error=False):
@ -43,11 +47,27 @@ class AgentManager(periodic_task.PeriodicTasks):
"""List installed hardware."""
pass
def fpga_program(self, context, accelerator, image):
def fpga_program(self, context, deployable_uuid, image_uuid):
""" Program a FPGA regoin, image can be a url or local file"""
# TODO (Shaohe Feng) Get image from glance.
# And add claim and rollback logical.
raise NotImplementedError()
path = self._download_bitstream(context, image_uuid)
dep = self.cond_api.deployable_get(context, deployable_uuid)
driver = self.fpga_driver.create(dep.vendor)
driver.program(dep.address, path)
def _download_bitstream(self, context, bitstream_uuid):
"""download the bistream
:param context: the context
:param bistream_uuid: v4 uuid of the bitstream to reprogram
:returns: the path to bitstream downloaded, None if fail to download
"""
download_path = "/tmp/" + bitstream_uuid + ".bin"
self.image_api.download(context,
bitstream_uuid,
dest_path=download_path)
return download_path
@periodic_task.periodic_task(run_immediately=True)
def update_available_resource(self, context, startup=True):

View File

@ -21,7 +21,7 @@ import oslo_messaging as messaging
from cyborg.common import constants
from cyborg.common import rpc
from cyborg.objects import base as objects_base
from cyborg import objects
CONF = cfg.CONF
@ -50,3 +50,20 @@ class AgentAPI(object):
def hardware_list(self, context, values):
"""Signal the agent to find local hardware."""
pass
def program_fpga_with_bitstream(self,
context,
deployable_uuid,
bitstream_uuid):
"""Actiion to program a target FPGA"""
version = '1.0'
dpl_get = objects.Deployable.get(context, deployable_uuid)
if not dpl_get:
# TODO (Li Liu) throw an exception here
return 0
cctxt = self.client.prepare(server=dpl_get.host, version=version)
return cctxt.call(context, 'fpga_program',
deployable_uuid=deployable_uuid,
image_uuid=bitstream_uuid)

View File

@ -22,6 +22,7 @@ from wsme import types as wtypes
from cyborg.api.controllers import base
from cyborg.api.controllers import link
from cyborg.api.controllers.v1 import accelerators
from cyborg.api.controllers.v1 import deployables
from cyborg.api import expose
@ -51,6 +52,7 @@ class Controller(rest.RestController):
"""Version 1 API controller root"""
accelerators = accelerators.AcceleratorsController()
deployables = deployables.DeployablesController()
@expose.expose(V1)
def get(self):

View File

@ -28,6 +28,7 @@ from cyborg.common import exception
from cyborg.common import policy
from cyborg import objects
from cyborg.quota import QUOTAS
from cyborg.agent.rpcapi import AgentAPI
class Deployable(base.APIBase):
@ -151,10 +152,14 @@ class DeployablesController(base.CyborgController):
"""
image_uuid = program_info[0]['value'][0]['image_uuid']
agent_api = AgentAPI()
obj_dep = objects.Deployable.get(pecan.request.context, uuid)
# Set attribute of the new bitstream/image information
obj_dep.add_attribute(pecan.request.context, 'image_uuid', image_uuid)
# TODO (Li Liu) Trigger the program api in Agnet.
agent_api.program_fpga_with_bitstream(pecan.request.context,
uuid,
image_uuid)
return Deployable.convert_with_links(obj_dep)
@policy.authorize_wsgi("cyborg:deployable", "create", False)

View File

@ -92,7 +92,7 @@ class TestFPGADriver(base.TestCase):
b = "0x5e"
d = "0x00"
f = "0x0"
expect_cmd = ['sudo', 'fpgaconf', '-b', b,
expect_cmd = ['sudo', '/usr/bin/fpgaconf', '-b', b,
'-d', d, '-f', f, '/path/image']
mock_popen.return_value = p()
intel = FPGADriver.create("intel")

View File

@ -80,7 +80,7 @@ class TestIntelFPGADriver(base.TestCase):
b = "0x5e"
d = "0x00"
f = "0x0"
expect_cmd = ['sudo', 'fpgaconf', '-b', b,
expect_cmd = ['sudo', '/usr/bin/fpgaconf', '-b', b,
'-d', d, '-f', f, '/path/image']
mock_popen.return_value = p()
intel = IntelFPGADriver()

View File

@ -19,6 +19,7 @@ from six.moves import http_client
from cyborg.api.controllers.v1.deployables import Deployable
from cyborg.tests.unit.api.controllers.v1 import base as v1_test
from cyborg.tests.unit import fake_deployable
from cyborg.agent.rpcapi import AgentAPI
class TestFPGAProgramController(v1_test.APITestV1):
@ -29,13 +30,15 @@ class TestFPGAProgramController(v1_test.APITestV1):
self.deployable_uuids = ['0acbf8d6-e02a-4394-aae3-57557d209498']
@mock.patch('cyborg.objects.Deployable.get')
def test_program(self, mock_get_dep):
@mock.patch('cyborg.agent.rpcapi.AgentAPI.program_fpga_with_bitstream')
def test_program(self, mock_program, mock_get_dep):
self.headers['X-Roles'] = 'admin'
self.headers['Content-Type'] = 'application/json'
dep_uuid = self.deployable_uuids[0]
fake_dep = fake_deployable.fake_deployable_obj(self.context,
uuid=dep_uuid)
mock_get_dep.return_value = fake_dep
mock_program.return_value = None
body = [{"image_uuid": "9a17439a-85d0-4c53-a3d3-0f68a2eac896"}]
response = self.\
patch_json('/accelerators/deployables/%s/program' % dep_uuid,