-
Notifications
You must be signed in to change notification settings - Fork 355
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add hitachi vsp storage driver to community #388
Conversation
Codecov Report
@@ Coverage Diff @@
## v0.8.0-maint #388 +/- ##
================================================
+ Coverage 66.91% 67.04% +0.12%
================================================
Files 90 93 +3
Lines 6399 6700 +301
Branches 748 784 +36
================================================
+ Hits 4282 4492 +210
- Misses 1872 1944 +72
- Partials 245 264 +19
|
@@ -0,0 +1,220 @@ | |||
# Copyright 2020 The SODA Authors. | |||
# Copyright (c) 2016 Huawei Technologies Co., Ltd. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove huawei copyright
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove d
delfin/drivers/hds/vsp/vspstor.py
Outdated
@@ -0,0 +1,266 @@ | |||
# Copyright 2020 The SODA Authors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
File name should be lower case with underscore.
HDSVSP_SESSION_ID = None | ||
STORAGE_DEVICE_ID = None | ||
DEVICE_MODEL = None | ||
SERIALNUMBER = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these constants? Should these be member variable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when login or get_device_id everytime,they will be refresh
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, so I think it should be member variables and should not be upper case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
now changed them to member variables
.format(res.status_code, res.text)) | ||
# if method is logout,return immediately | ||
if method == 'DELETE' and RestHandler.\ | ||
REST_LOGOUT_URL in url: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is the definition of REST_LOGOUT_URL
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
elif res.status_code == 503: | ||
raise exception.InvalidResults(res.text) | ||
else: | ||
LOG.error('Rest exec failed') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please give more details in this log about what rest command exec failed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
have changed
raise exception.InvalidResults(err_msg) | ||
|
||
def get_resinfo_call(self, url, data=None, method=None, resName=None): | ||
rejson = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Local variable name rejson
is not correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
have changed
def logout(self): | ||
try: | ||
url = RestHandler.HDSVSP_LOGOUT_URL | ||
if RestHandler.HDSVSP_SESSION_ID is not None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If RestHandler.HDSVSP_SESSION_ID
is none, the url is RestHandler.HDSVSP_LOGOUT_URL
, then we call delete of this url, what would happen? All the sessions would be deleted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed
def get_specific_storage(self): | ||
url = '%s%s' % \ | ||
(RestHandler.HDSVSP_COMM_URL, RestHandler.STORAGE_DEVICE_ID) | ||
rejson = self.get_resinfo_call(url, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Local variable name should be imporved.
Please check all other local variable names.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed
LOG.error("Get device id error: %s", six.text_type(e)) | ||
raise e | ||
|
||
def get_specific_storage(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should it be get_storage
?
delfin/drivers/hds/vsp/vspstor.py
Outdated
self.rest_client = RestClient(**kwargs) | ||
self.rest_handler = rest_handler.RestHandler(self.rest_client) | ||
self.rest_handler.get_device_id() | ||
self.rest_handler.login() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that everytime login()
was called, get_device_id()
need be called at first, so would it be better to put get_device_id()
into login()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
get_device_id() need at the first time,becuase we need device_id,when the session overdue and login again,we do not need get device again
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
rejson = None | ||
res = self.call(url, data, method) | ||
if res is not None: | ||
if res.status_code == consts.SUCCESS_STATUS_CODES: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to assign SUCCESS_STATUS_CODES
to status_code
manually?
res
should have its own status_code
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed
|
||
if res is None: | ||
LOG.error('Login res is None') | ||
raise exception.InvalidResults('res is None') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What res is None? And it should be started with capital letter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed
delfin/drivers/hds/vsp/consts.py
Outdated
ERROR_SESSION_INVALID_CODE = 403 | ||
ERROR_SESSION_IS_BEING_USED_CODE = 409 | ||
SUCCESS_STATUS_CODES = 200 | ||
# block size |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment seems to be meaningless.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SUCCESS_STATUS_CODES changed
|
||
HDSVSP_AUTH_KEY = 'Authorization' | ||
|
||
def __init__(self, restclient): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
restclient
should be rest_client
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed
delfin/drivers/hds/vsp/consts.py
Outdated
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
ERROR_CONNECT_TO_SERVER = -403 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ERROR_CONNECT_TO_SERVER and LOGIN_SOCKET_TIMEOUT not used
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed
LOG.error(err_msg) | ||
raise exception.InvalidResults(err_msg) | ||
|
||
def get_resinfo_call(self, url, data=None, method=None, resName=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this function is going to 'get' resource info, should the method always be 'GET'?
If the method always be 'GET', we do not need to set method as parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not always 'GET'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For example?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked that,get_resinfo_call just is GET,have changed
delfin/drivers/hds/vsp/vspstor.py
Outdated
|
||
def __init__(self, **kwargs): | ||
super().__init__(**kwargs) | ||
self.rest_client = RestClient(**kwargs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One doubt.
HdsVspDriver
have rest_client
and rest_handler
, and rest_handler
has rest_client
, so when should HdsVspDriver
use rest_client
and when use rest_handler
? What the difference between rest_client
and rest_handler
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rest_handler will use rest_client,and in HdsVspDriver, i init rest_client first and init rest_handler with it to rest_handler,it's a same rest_client
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rest_client just do rest init, http request,rest_handler do bussiness
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but for a storage driver, only one rest object is enough, two object for rest would confuse other developers.
If rest_handler
already has rest_client
, would it be better that not operate rest_client directly anymore?
Or we can make rest_handler
a sub class of rest_client
, so it can has all the method what rest_client
has.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed
delfin/drivers/hds/vsp/vspstor.py
Outdated
if pools_info is not None: | ||
pools = pools_info.get('data') | ||
else: | ||
return pool_list |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This branch meanings some error during get_all_pools()
? Or some other means?
I'm concerning about that, if I got a empty list from list_storage_pools()
, it means actually there is no pool or met some issue during querying pool info?
Same for list_volumes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes,there may be met some issue during querying pool info,so i return a empty list
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So when I get an empty list from list_storage_pools
, how can I know whether it has no pool or it has pools but I met some issue when querying?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed
ibm storwize_svc add sshpool and fixed some issue (#381)
from delfin.drivers.hitachi.vsp.rest_handler import RestHandler | ||
from delfin.drivers.hitachi.vsp.vsp_stor import HitachiVspDriver | ||
from delfin.drivers.utils.rest_client import RestClient | ||
from requests import Session |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why move this import sentence to this line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed
LOG = logging.getLogger(__name__) | ||
|
||
|
||
class RestHandler(RestClient): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this new class and why can't the existing res_client util be used/enhanced?
used_total = total_total - free_total | ||
else: | ||
free_total = 0 | ||
total_total = 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we think of some better variable name? like total_total -> total_capacity or total_raw_cap
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed
'description': 'Hitachi VSP Pool', | ||
'status': status, | ||
'storage_type': storage_type, | ||
'subscribed_capacity': int(total_cap), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How come total_cap and subscribed_Cap be same?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happened to this comment?
volume_list = [] | ||
volumes = volumes_info.get('data') | ||
for volume in volumes: | ||
if volume.get('emulationType') == 'NOT DEFINED': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if a volume doesn't have emulation type, where will be the capacity or storage be accounted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in hitachi rest api of the volume,there always have emulationType
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then what is this 'NOT DEFINED?
|
||
total_cap = \ | ||
int(volume.get('blockCapacity')) * consts.BLOCK_SIZE | ||
used_cap = \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is going to screw the storage report. Used_cap and total_cap is same so free_cap is 0 always.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making free =0 may be true for a thick , because total_capacity=allocated_capacity (which is used from the perspective of array). but there should be a beeter way to update this for a thin volume. please check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes,i kown that,but there is no used_capacity or free_capacity
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So for thin devices, won't the Storage Summary report be affected by this?
|
||
return alert_list | ||
|
||
def add_trap_config(self, context, trap_config): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
put a TODO if it has to be implemented later, else put comment
delfin/drivers/hitachi/vsp/consts.py
Outdated
ERROR_SESSION_IS_BEING_USED_CODE = 409 | ||
BLOCK_SIZE = 512 | ||
|
||
VSP_FXXX_GXXX_SERIES = ('VSP G350', 'VSP G370', 'VSP G700', 'VSP G900', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
VSP_F_G_SERIES is better for me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there also have like F200,G200 they are different
self.rest_handler.login() | ||
|
||
def reset_connection(self, context, **kwargs): | ||
self.rest_handler.logout() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
verify should be updated before login
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Verified accessing with the certificate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not yet
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
completed
'raw_capacity': int(total_capacity), | ||
'total_capacity': int(total_capacity), | ||
'used_capacity': int(total_capacity - free_capacity), | ||
'free_capacity': int(free_capacity) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it provide subscribed capacity?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, nit provide
|
||
total_cap = \ | ||
int(volume.get('blockCapacity')) * consts.BLOCK_SIZE | ||
used_cap = \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making free =0 may be true for a thick , because total_capacity=allocated_capacity (which is used from the perspective of array). but there should be a beeter way to update this for a thin volume. please check.
delfin/drivers/hitachi/vsp/consts.py
Outdated
ERROR_SESSION_IS_BEING_USED_CODE = 409 | ||
BLOCK_SIZE = 512 | ||
|
||
VSP_F_G_350_370_700_900_SERIES = ('VSP G350', 'VSP G370', 'VSP G700', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change to SUPPORTED_VSP_SERIES
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
I still see the comments not addressed. What is the plan for it? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to address the comments before merging?
Add hitachi vsp driver
Add hitachi vsp driver
* Code improvement (#363) * ibm storwize_svc add sshpool and fixed some issue (#381) Add storage driver for IBM Storwize and svc series * add hitachi vsp storage driver to community (#388) Add hitachi vsp driver * Fix vsp driver issue * change pool status and some optimize for vsp (#395) * rest api change timeout and fix trap parse (#401) * fix ssh excption error when the port is wrong and do some optimize (#402) * Update the value of 'update_at' of storage when going to sync the storage (#425) * Code improvement (#363) * ibm storwize_svc add sshpool and fixed some issue (#381) Add storage driver for IBM Storwize and svc series * add hitachi vsp storage driver to community (#388) Add hitachi vsp driver * Fix vsp driver issue * change pool status and some optimize for vsp (#395) * rest api change timeout and fix trap parse (#401) * fix ssh excption error when the port is wrong and do some optimize (#402) * Update the value of 'update_at' of storage when going to sync the storage (#425) * Fix rebase issue * Fixing CI failure issues Co-authored-by: ThisIsClark <liuyuchibubao@gmail.com> Co-authored-by: jiangyutan <69443713+jiangyutan@users.noreply.github.com> Co-authored-by: Joseph Vazhappilly <josephvp@gmail.com> Co-authored-by: root <pravin ranjan>
What this PR does / why we need it:
this PR is for hitachi vsp storage,it provide hitachi storage's information collect,such as system,pools,volumes,it support VSP F/G seriers,and VSP F/G 350,370,700,900 support get the alerts,other seriers do not support alerts For now.
Which issue this PR fixes (optional, in
fixes #<issue number>(, fixes #<issue_number>, ...)
format, will close that issue when PR gets merged): fixes #Special notes for your reviewer:
Release note: